GCC Code Coverage Report


Directory: ./
File: sql/log_event.cc
Date: 2022-12-13 11:44:05
Exec Total Coverage
Lines: 5899 6477 91.1%
Branches: 5319 8984 59.2%

Line Branch Exec Source
1 /*
2 Copyright (c) 2000, 2022, Oracle and/or its affiliates.
3 Copyright (c) 2018, Percona and/or its affiliates.
4 Copyright (c) 2009, 2016, MariaDB
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is also distributed with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have included with MySQL.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License, version 2.0, for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
25
26 #define LOG_SUBSYSTEM_TAG "Repl"
27
28 #include "sql/log_event.h"
29
30 #include <assert.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include "my_config.h"
35 #ifdef HAVE_SYS_TIME_H
36 #include <sys/time.h>
37 #endif
38 #include <algorithm>
39 #include <map>
40 #include <memory>
41 #include <string>
42 #include <utility>
43
44 #include "base64.h"
45 #include "decimal.h"
46 #include "libbinlogevents/export/binary_log_funcs.h" // my_timestamp_binary_length
47 #include "libbinlogevents/include/debug_vars.h"
48 #include "libbinlogevents/include/table_id.h"
49 #include "libbinlogevents/include/wrapper_functions.h"
50 #include "m_ctype.h"
51 #include "my_bitmap.h"
52 #include "my_byteorder.h"
53 #include "my_compiler.h"
54 #include "my_dbug.h"
55 #include "my_io.h"
56 #include "my_loglevel.h"
57 #include "my_macros.h"
58 #include "my_systime.h"
59 #include "my_table_map.h"
60 #include "my_time.h" // MAX_DATE_STRING_REP_LENGTH
61 #include "mysql.h" // MYSQL_OPT_MAX_ALLOWED_PACKET
62 #include "mysql/components/services/bits/psi_statement_bits.h"
63 #include "mysql/components/services/log_builtins.h"
64 #include "mysql/components/services/log_shared.h"
65 #include "mysql/psi/mysql_mutex.h"
66 #include "mysql/udf_registration_types.h"
67 #include "mysql_time.h"
68 #include "psi_memory_key.h"
69 #include "query_options.h"
70 #include "sql/auth/auth_acls.h"
71 #include "sql/binlog_reader.h"
72 #include "sql/field_common_properties.h"
73 #include "sql/my_decimal.h" // my_decimal
74 #include "sql/rpl_handler.h" // RUN_HOOK
75 #include "sql/rpl_tblmap.h"
76 #include "sql/sql_show_processlist.h" // pfs_processlist_enabled
77 #include "sql/system_variables.h"
78 #include "sql/tc_log.h"
79 #include "sql/xa/sql_cmd_xa.h" // Sql_cmd_xa_*
80 #include "sql_const.h"
81 #include "sql_string.h"
82 #include "template_utils.h"
83
84 #ifndef MYSQL_SERVER
85 #include "client/mysqlbinlog.h"
86 #include "sql-common/json_binary.h"
87 #include "sql-common/json_dom.h" // Json_wrapper
88 #include "sql/json_diff.h" // enum_json_diff_operation
89 #endif
90
91 #ifdef MYSQL_SERVER
92
93 #include <errno.h>
94 #include <fcntl.h>
95
96 #include <cstdint>
97 #include <new>
98
99 #include "libbinlogevents/include/binary_log.h" // binary_log
100 #include "my_base.h"
101 #include "my_command.h"
102 #include "my_dir.h" // my_dir
103 #include "my_sqlcommand.h"
104 #include "mysql/plugin.h"
105 #include "mysql/psi/mysql_cond.h"
106 #include "mysql/psi/mysql_file.h"
107 #include "mysql/psi/mysql_stage.h"
108 #include "mysql/psi/mysql_statement.h"
109 #include "mysql/psi/mysql_transaction.h"
110 #include "mysql/psi/psi_statement.h"
111 #include "mysqld_error.h"
112 #include "prealloced_array.h"
113 #include "sql/auth/auth_common.h"
114 #include "sql/auth/sql_security_ctx.h"
115 #include "sql/basic_ostream.h"
116 #include "sql/binlog.h"
117 #include "sql/current_thd.h"
118 #include "sql/dd/types/abstract_table.h" // dd::enum_table_type
119 #include "sql/debug_sync.h" // debug_sync_set_action
120 #include "sql/derror.h" // ER_THD
121 #include "sql/enum_query_type.h"
122 #include "sql/field.h"
123 #include "sql/handler.h"
124 #include "sql/item.h"
125 #include "sql/item_func.h" // Item_func_set_user_var
126 #include "sql/key.h"
127 #include "sql/log.h" // Log_throttle
128 #include "sql/mdl.h"
129 #include "sql/mysqld.h" // lower_case_table_names server_uuid ...
130 #include "sql/protocol.h"
131 #include "sql/rpl_msr.h" // channel_map
132 #include "sql/rpl_mta_submode.h" // Mts_submode
133 #include "sql/rpl_replica.h" // use_slave_mask
134 #include "sql/rpl_reporting.h"
135 #include "sql/rpl_rli.h" // Relay_log_info
136 #include "sql/rpl_rli_pdb.h" // Slave_job_group
137 #include "sql/sp_head.h" // sp_name
138 #include "sql/sql_base.h" // close_thread_tables
139 #include "sql/sql_bitmap.h"
140 #include "sql/sql_class.h"
141 #include "sql/sql_cmd.h"
142 #include "sql/sql_connect.h" //update_global_user_stats
143 #include "sql/sql_data_change.h"
144 #include "sql/sql_db.h" // load_db_opt_by_name
145 #include "sql/sql_digest_stream.h"
146 #include "sql/sql_error.h"
147 #include "sql/sql_exchange.h" // sql_exchange
148 #include "sql/sql_gipk.h"
149 #include "sql/sql_lex.h"
150 #include "sql/sql_list.h" // I_List
151 #include "sql/sql_load.h" // Sql_cmd_load_table
152 #include "sql/sql_locale.h" // my_locale_by_number
153 #include "sql/sql_parse.h" // mysql_test_parse_for_slave
154 #include "sql/sql_plugin.h" // plugin_foreach
155 #include "sql/sql_show.h" // append_identifier
156 #include "sql/sql_tablespace.h" // Sql_cmd_tablespace
157 #include "sql/table.h"
158 #include "sql/thd_raii.h" // Disable_index_extensions_switch_guard
159 #include "sql/transaction.h" // trans_rollback_stmt
160 #include "sql/transaction_info.h"
161 #include "sql/tztime.h" // Time_zone
162 #include "thr_lock.h"
163
164 #ifdef WITH_WSREP
165 #include "service_wsrep.h"
166 #include "wsrep_mysqld.h"
167 #include "wsrep_xid.h"
168 #endif /* WITH_WSREP */
169
170 #define window_size Log_throttle::LOG_THROTTLE_WINDOW_SIZE
171 Error_log_throttle slave_ignored_err_throttle(
172 window_size, INFORMATION_LEVEL, ER_SERVER_SLAVE_IGNORED_TABLE, "Repl",
173 "Error log throttle: %lu time(s) Error_code: 1237"
174 " \"Slave SQL thread ignored the query because of"
175 " replicate-*-table rules\" got suppressed.");
176 #endif /* MYSQL_SERVER */
177
178 #include "libbinlogevents/include/codecs/binary.h"
179 #include "libbinlogevents/include/codecs/factory.h"
180 #include "libbinlogevents/include/compression/iterator.h"
181 #include "mysqld_error.h"
182 #include "sql/rpl_gtid.h"
183 #include "sql/rpl_record.h" // enum_row_image_type, Bit_reader
184 #include "sql/rpl_utility.h"
185 #include "sql/xa_aux.h"
186
187 struct mysql_mutex_t;
188
189 PSI_memory_key key_memory_log_event;
190 PSI_memory_key key_memory_Incident_log_event_message;
191 PSI_memory_key key_memory_Rows_query_log_event_rows_query;
192
193 using std::max;
194 using std::min;
195
196 /**
197 BINLOG_CHECKSUM variable.
198 */
199 const char *binlog_checksum_type_names[] = {"NONE", "CRC32", NullS};
200
201 unsigned int binlog_checksum_type_length[] = {sizeof("NONE") - 1,
202 sizeof("CRC32") - 1, 0};
203
204 TYPELIB binlog_checksum_typelib = {
205 array_elements(binlog_checksum_type_names) - 1, "",
206 binlog_checksum_type_names, binlog_checksum_type_length};
207
208 #define log_cs &my_charset_latin1
209
210 /*
211 Size of buffer for printing a double in format %.<PREC>g
212
213 optional '-' + optional zero + '.' + PREC digits + 'e' + sign +
214 exponent digits + '\0'
215 */
216 #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1)
217
218 #if defined(MYSQL_SERVER)
219 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD *thd);
220
221 377 static const char *HA_ERR(int i) {
222 /*
223 This function should only be called in case of an error
224 was detected
225 */
226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 377 times.
377 assert(i != 0);
227
8/56
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 73 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 17 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 104 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 13 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 4 times.
✓ Branch 29 taken 4 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✓ Branch 55 taken 127 times.
377 switch (i) {
228 35 case HA_ERR_KEY_NOT_FOUND:
229 35 return "HA_ERR_KEY_NOT_FOUND";
230 73 case HA_ERR_FOUND_DUPP_KEY:
231 73 return "HA_ERR_FOUND_DUPP_KEY";
232 case HA_ERR_RECORD_CHANGED:
233 return "HA_ERR_RECORD_CHANGED";
234 case HA_ERR_WRONG_INDEX:
235 return "HA_ERR_WRONG_INDEX";
236 case HA_ERR_CRASHED:
237 return "HA_ERR_CRASHED";
238 case HA_ERR_WRONG_IN_RECORD:
239 return "HA_ERR_WRONG_IN_RECORD";
240 case HA_ERR_OUT_OF_MEM:
241 return "HA_ERR_OUT_OF_MEM";
242 case HA_ERR_NOT_A_TABLE:
243 return "HA_ERR_NOT_A_TABLE";
244 case HA_ERR_WRONG_COMMAND:
245 return "HA_ERR_WRONG_COMMAND";
246 case HA_ERR_OLD_FILE:
247 return "HA_ERR_OLD_FILE";
248 case HA_ERR_NO_ACTIVE_RECORD:
249 return "HA_ERR_NO_ACTIVE_RECORD";
250 case HA_ERR_RECORD_DELETED:
251 return "HA_ERR_RECORD_DELETED";
252 case HA_ERR_RECORD_FILE_FULL:
253 return "HA_ERR_RECORD_FILE_FULL";
254 case HA_ERR_INDEX_FILE_FULL:
255 return "HA_ERR_INDEX_FILE_FULL";
256 17 case HA_ERR_END_OF_FILE:
257 17 return "HA_ERR_END_OF_FILE";
258 case HA_ERR_UNSUPPORTED:
259 return "HA_ERR_UNSUPPORTED";
260 case HA_ERR_TOO_BIG_ROW:
261 return "HA_ERR_TOO_BIG_ROW";
262 case HA_WRONG_CREATE_OPTION:
263 return "HA_WRONG_CREATE_OPTION";
264 case HA_ERR_FOUND_DUPP_UNIQUE:
265 return "HA_ERR_FOUND_DUPP_UNIQUE";
266 case HA_ERR_UNKNOWN_CHARSET:
267 return "HA_ERR_UNKNOWN_CHARSET";
268 case HA_ERR_WRONG_MRG_TABLE_DEF:
269 return "HA_ERR_WRONG_MRG_TABLE_DEF";
270 case HA_ERR_CRASHED_ON_REPAIR:
271 return "HA_ERR_CRASHED_ON_REPAIR";
272 case HA_ERR_CRASHED_ON_USAGE:
273 return "HA_ERR_CRASHED_ON_USAGE";
274 104 case HA_ERR_LOCK_WAIT_TIMEOUT:
275 104 return "HA_ERR_LOCK_WAIT_TIMEOUT";
276 case HA_ERR_LOCK_TABLE_FULL:
277 return "HA_ERR_LOCK_TABLE_FULL";
278 case HA_ERR_READ_ONLY_TRANSACTION:
279 return "HA_ERR_READ_ONLY_TRANSACTION";
280 13 case HA_ERR_LOCK_DEADLOCK:
281 13 return "HA_ERR_LOCK_DEADLOCK";
282 case HA_ERR_CANNOT_ADD_FOREIGN:
283 return "HA_ERR_CANNOT_ADD_FOREIGN";
284 4 case HA_ERR_NO_REFERENCED_ROW:
285 4 return "HA_ERR_NO_REFERENCED_ROW";
286 4 case HA_ERR_ROW_IS_REFERENCED:
287 4 return "HA_ERR_ROW_IS_REFERENCED";
288 case HA_ERR_NO_SAVEPOINT:
289 return "HA_ERR_NO_SAVEPOINT";
290 case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
291 return "HA_ERR_NON_UNIQUE_BLOCK_SIZE";
292 case HA_ERR_NO_SUCH_TABLE:
293 return "HA_ERR_NO_SUCH_TABLE";
294 case HA_ERR_TABLE_EXIST:
295 return "HA_ERR_TABLE_EXIST";
296 case HA_ERR_NO_CONNECTION:
297 return "HA_ERR_NO_CONNECTION";
298 case HA_ERR_NULL_IN_SPATIAL:
299 return "HA_ERR_NULL_IN_SPATIAL";
300 case HA_ERR_TABLE_DEF_CHANGED:
301 return "HA_ERR_TABLE_DEF_CHANGED";
302 case HA_ERR_NO_PARTITION_FOUND:
303 return "HA_ERR_NO_PARTITION_FOUND";
304 case HA_ERR_RBR_LOGGING_FAILED:
305 return "HA_ERR_RBR_LOGGING_FAILED";
306 case HA_ERR_DROP_INDEX_FK:
307 return "HA_ERR_DROP_INDEX_FK";
308 case HA_ERR_FOREIGN_DUPLICATE_KEY:
309 return "HA_ERR_FOREIGN_DUPLICATE_KEY";
310 case HA_ERR_TABLE_NEEDS_UPGRADE:
311 return "HA_ERR_TABLE_NEEDS_UPGRADE";
312 case HA_ERR_TABLE_READONLY:
313 return "HA_ERR_TABLE_READONLY";
314 case HA_ERR_AUTOINC_READ_FAILED:
315 return "HA_ERR_AUTOINC_READ_FAILED";
316 case HA_ERR_AUTOINC_ERANGE:
317 return "HA_ERR_AUTOINC_ERANGE";
318 case HA_ERR_GENERIC:
319 return "HA_ERR_GENERIC";
320 case HA_ERR_RECORD_IS_THE_SAME:
321 return "HA_ERR_RECORD_IS_THE_SAME";
322 case HA_ERR_LOGGING_IMPOSSIBLE:
323 return "HA_ERR_LOGGING_IMPOSSIBLE";
324 case HA_ERR_CORRUPT_EVENT:
325 return "HA_ERR_CORRUPT_EVENT";
326 case HA_ERR_ROWS_EVENT_APPLY:
327 return "HA_ERR_ROWS_EVENT_APPLY";
328 case HA_ERR_FK_DEPTH_EXCEEDED:
329 return "HA_ERR_FK_DEPTH_EXCEEDED";
330 case HA_ERR_INNODB_READ_ONLY:
331 return "HA_ERR_INNODB_READ_ONLY";
332 case HA_ERR_COMPUTE_FAILED:
333 return "HA_ERR_COMPUTE_FAILED";
334 case HA_ERR_NO_WAIT_LOCK:
335 return "HA_ERR_NO_WAIT_LOCK";
336 case HA_ERR_FTS_TOO_MANY_NESTED_EXP:
337 return "HA_ERR_FTS_TOO_MANY_NESTED_EXP";
338 }
339 127 return "No Error!";
340 }
341
342 /**
343 Error reporting facility for Rows_log_event::do_apply_event
344
345 @param level error, warning or info
346 @param ha_error HA_ERR_ code
347 @param rli pointer to the active Relay_log_info instance
348 @param thd pointer to the slave thread's thd
349 @param table pointer to the event's table object
350 @param type the type of the event
351 @param log_name the master binlog file name
352 @param pos the master binlog file pos (the next after the event)
353
354 */
355 381 static void inline slave_rows_error_report(enum loglevel level, int ha_error,
356 Relay_log_info const *rli, THD *thd,
357 TABLE *table, const char *type,
358 const char *log_name, ulong pos) {
359
2/2
✓ Branch 0 taken 377 times.
✓ Branch 1 taken 4 times.
381 const char *handler_error = (ha_error ? HA_ERR(ha_error) : nullptr);
360 bool is_group_replication_applier_channel =
361
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 channel_map.is_group_replication_channel_name(
362 381 (const_cast<Relay_log_info *>(rli))->get_channel(), true);
363 char buff[MAX_SLAVE_ERRMSG], *slider;
364 381 const char *buff_end = buff + sizeof(buff);
365 size_t len;
366 Diagnostics_area::Sql_condition_iterator it =
367
1/2
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
381 thd->get_stmt_da()->sql_conditions();
368 const Sql_condition *err;
369 381 buff[0] = 0;
370
371
5/6
✓ Branch 0 taken 381 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 407 times.
✓ Branch 3 taken 381 times.
✓ Branch 4 taken 406 times.
✓ Branch 5 taken 1 times.
788 for (err = it++, slider = buff; err && slider < buff_end - 1;
372 407 slider += len, err = it++) {
373
1/2
✓ Branch 0 taken 407 times.
✗ Branch 1 not taken.
406 len = snprintf(slider, buff_end - slider, " %s, Error_code: %d;",
374 err->message_text(), err->mysql_errno());
375 }
376
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 365 times.
382 if (is_group_replication_applier_channel) {
377
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 if (ha_error != 0) {
378
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
34 rli->report(level,
379
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
380 : ER_UNKNOWN_ERROR,
381 "Could not execute %s event on table %s.%s;"
382 "%s handler error %s",
383
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 type, table->s->db.str, table->s->table_name.str, buff,
384 handler_error == nullptr ? "<unknown>" : handler_error);
385 } else {
386 rli->report(level,
387 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
388 : ER_UNKNOWN_ERROR,
389 "Could not execute %s event on table %s.%s;"
390 "%s",
391 type, table->s->db.str, table->s->table_name.str, buff);
392 }
393 } else {
394
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 5 times.
365 if (ha_error != 0) {
395
2/4
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 361 times.
✗ Branch 3 not taken.
721 rli->report(level,
396
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
361 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
397 : ER_UNKNOWN_ERROR,
398 "Could not execute %s event on table %s.%s;"
399 "%s handler error %s; "
400 "the event's master log %s, end_log_pos %lu",
401
1/2
✓ Branch 0 taken 361 times.
✗ Branch 1 not taken.
360 type, table->s->db.str, table->s->table_name.str, buff,
402 handler_error == nullptr ? "<unknown>" : handler_error,
403 log_name, pos);
404 } else {
405
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 rli->report(level,
406
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
407 : ER_UNKNOWN_ERROR,
408 "Could not execute %s event on table %s.%s;"
409 "%s the event's master log %s, end_log_pos %lu",
410
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
5 type, table->s->db.str, table->s->table_name.str, buff,
411 log_name, pos);
412 }
413 }
414 382 }
415
416 /**
417 Set the rewritten database, or current database if it should not be
418 rewritten, into THD.
419
420 @param thd THD handle
421 @param db database name
422 @param db_len the length of database name
423
424 @retval true if the passed db is rewritten.
425 @retval false if the passed db is not rewritten.
426 */
427 556656 static bool set_thd_db(THD *thd, const char *db, size_t db_len) {
428 556656 bool need_increase_counter = false;
429 char lcase_db_buf[NAME_LEN + 1];
430 LEX_CSTRING new_db;
431 556656 new_db.length = db_len;
432
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 556509 times.
556656 if (lower_case_table_names) {
433 147 my_stpcpy(lcase_db_buf, db);
434
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 my_casedn_str(system_charset_info, lcase_db_buf);
435 147 new_db.str = lcase_db_buf;
436 } else
437 556509 new_db.str = db;
438
439 /* This function is called by a slave thread. */
440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556656 times.
556656 assert(thd->rli_slave);
441
442 556656 Rpl_filter *rpl_filter = thd->rli_slave->rpl_filter;
443
1/2
✓ Branch 0 taken 556744 times.
✗ Branch 1 not taken.
556656 new_db.str = rpl_filter->get_rewrite_db(new_db.str, &new_db.length);
444
445
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 556597 times.
556744 if (lower_case_table_names) {
446 /* lcase_db_buf != new_db.str means that lcase_db_buf is rewritten. */
447
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 127 times.
147 if (strcmp(lcase_db_buf, new_db.str)) need_increase_counter = true;
448 } else {
449 /* db != new_db.str means that db is rewritten. */
450
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 556390 times.
556597 if (strcmp(db, new_db.str)) need_increase_counter = true;
451 }
452
453
1/2
✓ Branch 0 taken 557044 times.
✗ Branch 1 not taken.
556744 thd->set_db(new_db);
454
455 557044 return need_increase_counter;
456 }
457
458 #endif
459
460 /*
461 pretty_print_str()
462 */
463
464 #ifndef MYSQL_SERVER
465 168 static inline void pretty_print_str(IO_CACHE *cache, const char *str,
466 size_t len, bool identifier) {
467 168 const char *end = str + len;
468
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
168 my_b_printf(cache, identifier ? "`" : "\'");
469
2/2
✓ Branch 0 taken 3846 times.
✓ Branch 1 taken 168 times.
4014 while (str < end) {
470 char c;
471
5/9
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 228 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 3615 times.
3846 switch ((c = *str++)) {
472 case '\n':
473 my_b_printf(cache, "\\n");
474 break;
475 case '\r':
476 my_b_printf(cache, "\\r");
477 break;
478 1 case '\\':
479 1 my_b_printf(cache, "\\\\");
480 1 break;
481 case '\b':
482 my_b_printf(cache, "\\b");
483 break;
484 case '\t':
485 my_b_printf(cache, "\\t");
486 break;
487 1 case '\'':
488 1 my_b_printf(cache, "\\'");
489 1 break;
490 228 case 0:
491 228 my_b_printf(cache, "\\0");
492 228 break;
493 1 case '`':
494
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (identifier)
495 1 my_b_printf(cache, "``");
496 else
497 my_b_printf(cache, "`");
498 1 break;
499 3615 default:
500 3615 my_b_printf(cache, "%c", c);
501 3615 break;
502 }
503 }
504
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 84 times.
168 my_b_printf(cache, identifier ? "`" : "\'");
505 168 }
506
507 /**
508 Print src as an string enclosed with "'"
509
510 @param[out] cache IO_CACHE where the string will be printed.
511 @param[in] str the string will be printed.
512 @param[in] len length of the string.
513 */
514 84 static inline void pretty_print_str(IO_CACHE *cache, const char *str,
515 size_t len) {
516 84 pretty_print_str(cache, str, len, false);
517 84 }
518
519 /**
520 Print src as an identifier enclosed with "`"
521
522 @param[out] cache IO_CACHE where the identifier will be printed.
523 @param[in] str the string will be printed.
524 @param[in] len length of the string.
525 */
526 84 static inline void pretty_print_identifier(IO_CACHE *cache, const char *str,
527 size_t len) {
528 84 pretty_print_str(cache, str, len, true);
529 84 }
530
531 #endif /* !MYSQL_SERVER */
532
533 #if defined(MYSQL_SERVER)
534
535 1112253 static void clear_all_errors(THD *thd, Relay_log_info *rli) {
536 1112253 thd->is_slave_error = false;
537 1112253 thd->clear_error();
538 1112367 rli->clear_error();
539
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1112317 times.
1112371 if (rli->workers_array_initialized) {
540
2/2
✓ Branch 0 taken 164 times.
✓ Branch 1 taken 54 times.
218 for (size_t i = 0; i < rli->get_worker_count(); i++) {
541 164 rli->get_worker(i)->clear_error();
542 }
543 }
544 1112371 }
545
546 402 inline int idempotent_error_code(int err_code) {
547 402 int ret = 0;
548
549
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 269 times.
402 switch (err_code) {
550 case 0:
551 ret = 1;
552 break;
553 /*
554 The following list of "idempotent" errors
555 means that an error from the list might happen
556 because of idempotent (more than once)
557 applying of a binlog file.
558 Notice, that binlog has a ddl operation its
559 second applying may cause
560
561 case HA_ERR_TABLE_DEF_CHANGED:
562 case HA_ERR_CANNOT_ADD_FOREIGN:
563
564 which are not included into to the list.
565
566 Note that HA_ERR_RECORD_DELETED is not in the list since
567 do_exec_row() should not return that error code.
568 */
569 133 case HA_ERR_RECORD_CHANGED:
570 case HA_ERR_KEY_NOT_FOUND:
571 case HA_ERR_END_OF_FILE:
572 case HA_ERR_FOUND_DUPP_KEY:
573 case HA_ERR_FOUND_DUPP_UNIQUE:
574 case HA_ERR_FOREIGN_DUPLICATE_KEY:
575 case HA_ERR_NO_REFERENCED_ROW:
576 case HA_ERR_ROW_IS_REFERENCED:
577 133 ret = 1;
578 133 break;
579 269 default:
580 269 ret = 0;
581 269 break;
582 }
583 402 return (ret);
584 }
585
586 /**
587 Ignore error code specified on command line.
588 */
589
590 560471 int ignored_error_code(int err_code) {
591
4/4
✓ Branch 0 taken 559846 times.
✓ Branch 1 taken 625 times.
✓ Branch 2 taken 452 times.
✓ Branch 3 taken 559394 times.
560923 return ((err_code == ER_SLAVE_IGNORED_TABLE) ||
592
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 305 times.
560923 (use_slave_mask && bitmap_is_set(&slave_error_mask, err_code)));
593 }
594
595 /*
596 This function converts an engine's error to a server error.
597
598 If the thread does not have an error already reported, it tries to
599 define it by calling the engine's method print_error. However, if a
600 mapping is not found, it uses the ER_UNKNOWN_ERROR and prints out a
601 warning message.
602 */
603 688 static int convert_handler_error(int error, THD *thd, TABLE *table) {
604
2/2
✓ Branch 0 taken 666 times.
✓ Branch 1 taken 23 times.
688 uint actual_error = (thd->is_error() ? thd->get_stmt_da()->mysql_errno() : 0);
605
606
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 666 times.
689 if (actual_error == 0) {
607 23 table->file->print_error(error, MYF(0));
608
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 actual_error = (thd->is_error() ? thd->get_stmt_da()->mysql_errno()
609 : ER_UNKNOWN_ERROR);
610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if (actual_error == ER_UNKNOWN_ERROR)
611 LogErr(WARNING_LEVEL, ER_UNKNOWN_ERROR_DETECTED_IN_SE, error);
612 }
613
614 689 return (actual_error);
615 }
616
617 554959 inline bool concurrency_error_code(int error) {
618
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 554951 times.
554959 switch (error) {
619 8 case ER_LOCK_WAIT_TIMEOUT:
620 case ER_LOCK_DEADLOCK:
621 case ER_XA_RBDEADLOCK:
622 8 return true;
623 554951 default:
624 554951 return (false);
625 }
626 }
627
628 556614 inline bool unexpected_error_code(int unexpected_error) {
629
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 556609 times.
556614 switch (unexpected_error) {
630 5 case ER_NET_READ_ERROR:
631 case ER_NET_ERROR_ON_WRITE:
632 case ER_QUERY_INTERRUPTED:
633 case ER_SERVER_SHUTDOWN:
634 case ER_NEW_ABORTING_CONNECTION:
635 5 return (true);
636 556609 default:
637 556609 return (false);
638 }
639 }
640
641 /*
642 pretty_print_str()
643 */
644 20096 static void pretty_print_str(String *packet, const char *str, size_t len) {
645 20096 packet->append('\'');
646
647
2/2
✓ Branch 0 taken 302874 times.
✓ Branch 1 taken 20096 times.
322970 for (size_t i = 0; i < len; i++) {
648
8/8
✓ Branch 0 taken 4026 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2714 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2686 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 293434 times.
302874 switch (str[i]) {
649 4026 case '\n':
650
1/2
✓ Branch 0 taken 4026 times.
✗ Branch 1 not taken.
4026 packet->append("\\n");
651 4026 break;
652 2 case '\r':
653
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 packet->append("\\r");
654 2 break;
655 2714 case '\\':
656
1/2
✓ Branch 0 taken 2714 times.
✗ Branch 1 not taken.
2714 packet->append("\\\\");
657 2714 break;
658 2 case '\b':
659
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 packet->append("\\b");
660 2 break;
661 2686 case '\t':
662
1/2
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
2686 packet->append("\\t");
663 2686 break;
664 8 case '\'':
665
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 packet->append("\\'");
666 8 break;
667 2 case 0:
668
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 packet->append("\\0");
669 2 break;
670 293434 default:
671 293434 packet->append(str[i]);
672 293434 break;
673 }
674 }
675 20096 packet->append('\'');
676 20096 }
677
678 16080 static inline void pretty_print_str(String *packet, const String *str) {
679 16080 pretty_print_str(packet, str->ptr(), str->length());
680 16080 }
681
682 /**
683 Creates a temporary name for load data infile:.
684
685 @param buf Store new filename here
686 @param file_id File_id (part of file name)
687 @param event_server_id Event_id (part of file name)
688 @param ext Extension for file name
689
690 @return
691 Pointer to start of extension
692 */
693
694 189 static char *slave_load_file_stem(char *buf, uint file_id, int event_server_id,
695 const char *ext) {
696 char *res;
697 189 fn_format(buf, PREFIX_SQL_LOAD, replica_load_tmpdir, "", MY_UNPACK_FILENAME);
698 189 to_unix_path(buf);
699
700 189 buf = strend(buf);
701 189 int appended_length = sprintf(buf, "%s-%d-", server_uuid, event_server_id);
702 189 buf += appended_length;
703 189 res = longlong10_to_str(file_id, buf, 10);
704 189 my_stpcpy(res, ext); // Add extension last
705 189 return res; // Pointer to extension
706 }
707
708 /**
709 Delete all temporary files used for SQL_LOAD.
710 */
711
712 3671 static void cleanup_load_tmpdir() {
713 MY_DIR *dirp;
714 FILEINFO *file;
715 uint i;
716 char fname[FN_REFLEN], prefbuf[TEMP_FILE_MAX_LEN], *p;
717
718
2/4
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3671 times.
3671 if (!(dirp = my_dir(replica_load_tmpdir, MYF(0)))) return;
719
720 /*
721 When we are deleting temporary files, we should only remove
722 the files associated with the server id of our server.
723 We don't use event_server_id here because since we've disabled
724 direct binlogging of Create_file/Append_file/Exec_load events
725 we cannot meet Start_log event in the middle of events from one
726 LOAD DATA.
727 */
728
1/2
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
3671 p = strmake(prefbuf, STRING_WITH_LEN(PREFIX_SQL_LOAD));
729 3671 sprintf(p, "%s-", server_uuid);
730
731
2/2
✓ Branch 0 taken 21456 times.
✓ Branch 1 taken 3671 times.
25127 for (i = 0; i < dirp->number_off_files; i++) {
732 21456 file = dirp->dir_entry + i;
733
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 21448 times.
21456 if (is_prefix(file->name, prefbuf)) {
734
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 fn_format(fname, file->name, replica_load_tmpdir, "", MY_UNPACK_FILENAME);
735
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 mysql_file_delete(key_file_misc, fname, MYF(0));
736 }
737 }
738
739
1/2
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
3671 my_dirend(dirp);
740 }
741 #endif
742
743 template <typename T>
744 46892 bool net_field_length_checked(const uchar **packet, size_t *max_length,
745 T *out) {
746
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 23386 times.
46892 if (*max_length < 1) return true;
747 46772 const uchar *pos = *packet;
748
2/2
✓ Branch 0 taken 23017 times.
✓ Branch 1 taken 369 times.
46772 if (*pos < 251) {
749 46034 (*packet)++;
750 46034 (*max_length)--;
751 46034 *out = (T)*pos;
752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 369 times.
738 } else if (*pos == 251) {
753 (*packet)++;
754 (*max_length)--;
755 *out = (T)NULL_LENGTH;
756
2/2
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 140 times.
738 } else if (*pos == 252) {
757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 229 times.
458 if (*max_length < 3) return true;
758 458 (*packet) += 3;
759 458 (*max_length) -= 3;
760 458 *out = (T)uint2korr(pos + 1);
761
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 30 times.
280 } else if (*pos == 253) {
762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
220 if (*max_length < 4) return true;
763 220 (*packet) += 4;
764 220 (*max_length) -= 4;
765 220 *out = (T)uint3korr(pos + 1);
766 } else {
767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
60 if (*max_length < 9) return true;
768 60 (*packet) += 9;
769 60 (*max_length) -= 9;
770 60 *out = (T)uint8korr(pos + 1);
771 }
772 46772 return false;
773 }
774 template bool net_field_length_checked<size_t>(const uchar **packet,
775 size_t *max_length, size_t *out);
776 template bool net_field_length_checked<ulonglong>(const uchar **packet,
777 size_t *max_length,
778 ulonglong *out);
779
780 /**
781 Transforms a string into "" or its expression in 0x... form.
782 */
783
784 214 char *str_to_hex(char *to, const char *from, size_t len) {
785
2/2
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 3 times.
214 if (len) {
786 211 *to++ = '0';
787 211 *to++ = 'x';
788 211 to = octet2hex(to, from, len);
789 } else
790 3 to = my_stpcpy(to, "\"\"");
791 214 return to; // pointer to end 0 of 'to'
792 }
793
794 #ifdef MYSQL_SERVER
795
796 /**
797 Append a version of the 'from' string suitable for use in a query to
798 the 'to' string. To generate a correct escaping, the character set
799 information in 'csinfo' is used.
800 */
801
802 141037 int append_query_string(const THD *thd, const CHARSET_INFO *csinfo,
803 String const *from, String *to) {
804 char *beg, *ptr;
805 141037 size_t const orig_len = to->length();
806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141063 times.
141067 if (to->reserve(orig_len + from->length() * 2 + 3)) return 1;
807
808 141063 beg = to->c_ptr_quick() + to->length();
809 141056 ptr = beg;
810
2/2
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 140882 times.
141056 if (csinfo->escape_with_backslash_is_dangerous)
811 174 ptr = str_to_hex(ptr, from->ptr(), from->length());
812 else {
813 140882 *ptr++ = '\'';
814
2/2
✓ Branch 0 taken 140203 times.
✓ Branch 1 taken 679 times.
140882 if (!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) {
815 140219 ptr +=
816 140203 escape_string_for_mysql(csinfo, ptr, 0, from->ptr(), from->length());
817 } else {
818 679 const char *frm_str = from->ptr();
819
820
2/2
✓ Branch 0 taken 30697 times.
✓ Branch 1 taken 665 times.
31376 for (; frm_str < (from->ptr() + from->length()); frm_str++) {
821 /* Using '' way to represent "'" */
822
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 30675 times.
30697 if (*frm_str == '\'') *ptr++ = *frm_str;
823
824 30697 *ptr++ = *frm_str;
825 }
826 }
827
828 140884 *ptr++ = '\'';
829 }
830 141058 to->length(orig_len + ptr - beg);
831 141059 return 0;
832 }
833 #endif
834
835 /**
836 Prints a "session_var=value" string. Used by mysqlbinlog to print some SET
837 commands just before it prints a query.
838 */
839
840 #ifndef MYSQL_SERVER
841
842 19316 static void print_set_option(IO_CACHE *file, uint32 bits_changed, uint32 option,
843 uint32 flags, const char *name, bool *need_comma) {
844
2/2
✓ Branch 0 taken 19302 times.
✓ Branch 1 taken 14 times.
19316 if (bits_changed & option) {
845
2/2
✓ Branch 0 taken 14473 times.
✓ Branch 1 taken 4829 times.
19302 if (*need_comma) my_b_printf(file, ", ");
846 19302 my_b_printf(file, "%s=%d", name, static_cast<bool>(flags & option));
847 19302 *need_comma = true;
848 }
849 19316 }
850 #endif
851
852 #ifdef MYSQL_SERVER
853 11026584 Replicated_columns_view::Replicated_columns_view(
854 11026584 Replicated_columns_view::enum_replication_flow direction, THD const *thd)
855 11026584 : Replicated_columns_view{nullptr, direction, thd} {}
856
857 127394951 Replicated_columns_view::Replicated_columns_view(
858 TABLE const *target,
859 127394951 Replicated_columns_view::enum_replication_flow direction, THD const *thd)
860 127394951 : Table_columns_view{} {
861 127396743 filter_fn_type filter{nullptr};
862
863
2/2
✓ Branch 0 taken 111974177 times.
✓ Branch 1 taken 15422424 times.
127396601 if (direction == Replicated_columns_view::OUTBOUND)
864 314344630 filter = [this](TABLE const *table, size_t column_index) -> bool {
865 314344630 return this->outbound_filtering(table, column_index);
866 111974177 };
867 else
868 8219157 filter = [this](TABLE const *table, size_t column_index) -> bool {
869 8219157 return this->inbound_filtering(table, column_index);
870 15422424 };
871
872
1/2
✓ Branch 0 taken 127396376 times.
✗ Branch 1 not taken.
127396772 this->set_thd(thd) //
873
2/4
✓ Branch 0 taken 127395765 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127396907 times.
✗ Branch 3 not taken.
254792747 .set_filter(filter) //
874
1/2
✓ Branch 0 taken 127396371 times.
✗ Branch 1 not taken.
127396907 .set_table(target);
875 127396350 }
876
877 127744953 Replicated_columns_view &Replicated_columns_view::set_thd(THD const *thd) {
878 127744953 this->m_thd = thd;
879 127744953 this->init_fields_bitmaps();
880 127745853 return (*this);
881 }
882
883 8219055 bool Replicated_columns_view::is_inbound_filtering_enabled() {
884 16438135 return (this->m_thd == nullptr ||
885
2/2
✓ Branch 0 taken 3409111 times.
✓ Branch 1 taken 4809969 times.
8219080 this->m_thd->variables.immediate_server_version ==
886
1/2
✓ Branch 0 taken 8219080 times.
✗ Branch 1 not taken.
16438135 UNDEFINED_SERVER_VERSION ||
887
2/2
✓ Branch 0 taken 3409102 times.
✓ Branch 1 taken 9 times.
11628166 this->m_thd->variables.immediate_server_version >= 80018);
888 }
889
890 8219052 bool Replicated_columns_view::inbound_filtering(TABLE const *table,
891 size_t column_index) {
892
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 8219181 times.
8219052 if (!this->is_inbound_filtering_enabled()) return false;
893 // If the set of filtered columns is changed, we need to replicate the change
894 // in other blocks that reproduce the behavior - Rapid binlog parser, for
895 // instance.
896 8219181 return bitmap_is_set(&table->fields_for_functional_indexes, column_index);
897 }
898
899 314344462 bool Replicated_columns_view::outbound_filtering(TABLE const *table,
900 size_t column_index) {
901 // If the set of filtered columns is changed, we need to replicate the change
902 // in other blocks that reproduce the behavior - Rapid binlog parser, for
903 // instance.
904 314344462 return bitmap_is_set(&table->fields_for_functional_indexes, column_index);
905 }
906 #endif
907
908 /**************************************************************************
909 Log_event methods (= the parent class of all events)
910 **************************************************************************/
911
912 #ifdef MYSQL_SERVER
913
914 17036600 time_t Log_event::get_time() {
915 /* Not previously initialized */
916
3/4
✓ Branch 0 taken 270279 times.
✓ Branch 1 taken 16766321 times.
✓ Branch 2 taken 270280 times.
✗ Branch 3 not taken.
17036600 if (!common_header->when.tv_sec && !common_header->when.tv_usec) {
917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 270280 times.
270280 THD *tmp_thd = thd ? thd : current_thd;
918
2/2
✓ Branch 0 taken 238429 times.
✓ Branch 1 taken 31851 times.
270280 if (tmp_thd)
919 238429 common_header->when = tmp_thd->start_time;
920 else
921 31851 my_micro_time_to_timeval(my_micro_time(), &(common_header->when));
922 }
923 17036708 return (time_t)common_header->when.tv_sec;
924 }
925
926 #endif
927
928 /**
929 @return
930 returns the human readable name of the event's type
931 */
932
933 326176 const char *Log_event::get_type_str(Log_event_type type) {
934
29/33
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 154718 times.
✓ Branch 2 taken 1722 times.
✓ Branch 3 taken 22085 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 8082 times.
✓ Branch 8 taken 65 times.
✓ Branch 9 taken 4703 times.
✓ Branch 10 taken 34990 times.
✓ Branch 11 taken 14 times.
✓ Branch 12 taken 3 times.
✓ Branch 13 taken 5 times.
✓ Branch 14 taken 37 times.
✓ Branch 15 taken 31 times.
✓ Branch 16 taken 9 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 46 times.
✓ Branch 19 taken 59602 times.
✓ Branch 20 taken 5152 times.
✓ Branch 21 taken 4810 times.
✓ Branch 22 taken 4770 times.
✓ Branch 23 taken 18584 times.
✓ Branch 24 taken 3879 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 224 times.
✓ Branch 28 taken 100 times.
✓ Branch 29 taken 2492 times.
✓ Branch 30 taken 37 times.
✓ Branch 31 taken 3 times.
✓ Branch 32 taken 1 times.
326176 switch (type) {
935 7 case binary_log::STOP_EVENT:
936 7 return "Stop";
937 154718 case binary_log::QUERY_EVENT:
938 154718 return "Query";
939 1722 case binary_log::ROTATE_EVENT:
940 1722 return "Rotate";
941 22085 case binary_log::INTVAR_EVENT:
942 22085 return "Intvar";
943 4 case binary_log::APPEND_BLOCK_EVENT:
944 4 return "Append_block";
945 case binary_log::DELETE_FILE_EVENT:
946 return "Delete_file";
947 1 case binary_log::RAND_EVENT:
948 1 return "RAND";
949 8082 case binary_log::XID_EVENT:
950 8082 return "Xid";
951 65 case binary_log::USER_VAR_EVENT:
952 65 return "User var";
953 4703 case binary_log::FORMAT_DESCRIPTION_EVENT:
954 4703 return "Format_desc";
955 34990 case binary_log::TABLE_MAP_EVENT:
956 34990 return "Table_map";
957 14 case binary_log::WRITE_ROWS_EVENT_V1:
958 14 return "Write_rows_v1";
959 3 case binary_log::UPDATE_ROWS_EVENT_V1:
960 3 return "Update_rows_v1";
961 5 case binary_log::DELETE_ROWS_EVENT_V1:
962 5 return "Delete_rows_v1";
963 37 case binary_log::BEGIN_LOAD_QUERY_EVENT:
964 37 return "Begin_load_query";
965 31 case binary_log::EXECUTE_LOAD_QUERY_EVENT:
966 31 return "Execute_load_query";
967 9 case binary_log::INCIDENT_EVENT:
968 9 return "Incident";
969 case binary_log::IGNORABLE_LOG_EVENT:
970 return "Ignorable";
971 46 case binary_log::ROWS_QUERY_LOG_EVENT:
972 46 return "Rows_query";
973 59602 case binary_log::WRITE_ROWS_EVENT:
974 59602 return "Write_rows";
975 5152 case binary_log::UPDATE_ROWS_EVENT:
976 5152 return "Update_rows";
977 4810 case binary_log::DELETE_ROWS_EVENT:
978 4810 return "Delete_rows";
979 4770 case binary_log::GTID_LOG_EVENT:
980 4770 return "Gtid";
981 18584 case binary_log::ANONYMOUS_GTID_LOG_EVENT:
982 18584 return "Anonymous_Gtid";
983 3879 case binary_log::PREVIOUS_GTIDS_LOG_EVENT:
984 3879 return "Previous_gtids";
985 case binary_log::HEARTBEAT_LOG_EVENT:
986 case binary_log::HEARTBEAT_LOG_EVENT_V2:
987 return "Heartbeat";
988 case binary_log::TRANSACTION_CONTEXT_EVENT:
989 return "Transaction_context";
990 224 case binary_log::VIEW_CHANGE_EVENT:
991 224 return "View_change";
992 100 case binary_log::XA_PREPARE_LOG_EVENT:
993 100 return "XA_prepare";
994 2492 case binary_log::PARTIAL_UPDATE_ROWS_EVENT:
995 2492 return "Update_rows_partial";
996 37 case binary_log::TRANSACTION_PAYLOAD_EVENT:
997 37 return "Transaction_payload";
998 3 case binary_log::START_5_7_ENCRYPTION_EVENT:
999 3 return "Start_5_7_encryption";
1000 1 default:
1001 1 return "Unknown"; /* impossible */
1002 }
1003 }
1004
1005 326175 const char *Log_event::get_type_str() const {
1006 326175 return get_type_str(get_type_code());
1007 }
1008
1009 /*
1010 Log_event::Log_event()
1011 */
1012
1013 #ifdef MYSQL_SERVER
1014 16835658 Log_event::Log_event(THD *thd_arg, uint16 flags_arg,
1015 enum_event_cache_type cache_type_arg,
1016 enum_event_logging_type logging_type_arg,
1017 16835658 Log_event_header *header, Log_event_footer *footer)
1018 16835658 : temp_buf(nullptr),
1019 16835658 m_free_temp_buf_in_destructor(true),
1020 16835658 exec_time(0),
1021 16835658 event_cache_type(cache_type_arg),
1022 16835658 event_logging_type(logging_type_arg),
1023 16835658 crc(0),
1024 16835658 common_header(header),
1025 16835658 common_footer(footer),
1026 16835658 thd(thd_arg) {
1027 16835658 server_id = thd->server_id;
1028 16835658 common_header->unmasked_server_id = server_id;
1029 16835658 common_header->when = thd->start_time;
1030 16835658 common_header->log_pos = 0;
1031 16835658 common_header->flags = flags_arg;
1032 16835658 }
1033
1034 /**
1035 This minimal constructor is for when you are not even sure that there
1036 is a valid THD. For example in the server when we are shutting down or
1037 flushing logs after receiving a SIGHUP (then we must write a Rotate to
1038 the binlog but we have no THD, so we need this minimal constructor).
1039 */
1040
1041 351281 Log_event::Log_event(Log_event_header *header, Log_event_footer *footer,
1042 enum_event_cache_type cache_type_arg,
1043 351281 enum_event_logging_type logging_type_arg)
1044 351281 : temp_buf(nullptr),
1045 351281 m_free_temp_buf_in_destructor(true),
1046 351281 exec_time(0),
1047 351281 event_cache_type(cache_type_arg),
1048 351281 event_logging_type(logging_type_arg),
1049 351281 crc(0),
1050 351281 common_header(header),
1051 351281 common_footer(footer),
1052 351281 thd(nullptr) {
1053 351281 server_id = ::server_id;
1054 351281 common_header->unmasked_server_id = server_id;
1055 351281 }
1056 #endif /* MYSQL_SERVER */
1057
1058 /*
1059 Log_event::Log_event()
1060 */
1061
1062 16400062 Log_event::Log_event(Log_event_header *header, Log_event_footer *footer)
1063 16400062 : temp_buf(nullptr),
1064 16400062 m_free_temp_buf_in_destructor(true),
1065 16400062 exec_time(0),
1066 16400062 event_cache_type(EVENT_INVALID_CACHE),
1067 16400062 event_logging_type(EVENT_INVALID_LOGGING),
1068 16400062 crc(0),
1069 16400062 common_header(header),
1070 16400062 common_footer(footer) {
1071 #ifdef MYSQL_SERVER
1072 16121881 thd = nullptr;
1073 #endif
1074 /*
1075 Mask out any irrelevant parts of the server_id
1076 */
1077 16400062 server_id = common_header->unmasked_server_id & opt_server_id_mask;
1078 16400062 }
1079
1080 /*
1081 This method is not on header file to avoid using key_memory_log_event
1082 outside log_event.cc, allowing header file to be included on plugins.
1083 */
1084 20767029 void *Log_event::operator new(size_t size) {
1085 20767029 return my_malloc(key_memory_log_event, size, MYF(MY_WME | MY_FAE));
1086 }
1087
1088 #ifdef MYSQL_SERVER
1089 1360602 inline int Log_event::do_apply_event_worker(Slave_worker *w) {
1090
4/4
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 1360653 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 52 times.
1360602 DBUG_EXECUTE_IF("crash_in_a_worker", {
1091 /* we will crash a worker after waiting for
1092 2 seconds to make sure that other transactions are
1093 scheduled and completed */
1094 if (w->id == 2) {
1095 DBUG_SET("-d,crash_in_a_worker");
1096 my_sleep(2000000);
1097 DBUG_SUICIDE();
1098 }
1099 });
1100 1360705 return do_apply_event(w);
1101 }
1102
1103 15341 int Log_event::do_update_pos(Relay_log_info *rli) {
1104 15341 int error = 0;
1105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15341 times.
15341 assert(!rli->belongs_to_client());
1106
1107
1/2
✓ Branch 0 taken 15341 times.
✗ Branch 1 not taken.
15341 if (rli) error = rli->stmt_done(common_header->log_pos);
1108 15341 return error;
1109 }
1110
1111 1567368 Log_event::enum_skip_reason Log_event::do_shall_skip(Relay_log_info *rli) {
1112 /*
1113 The logic for slave_skip_counter is as follows:
1114
1115 - Events that are skipped because they have the same server_id as
1116 the slave do not decrease slave_skip_counter.
1117
1118 - Other events (that pass the server_id test) will decrease
1119 slave_skip_counter.
1120
1121 - Except in one case: if slave_skip_counter==1, it will only
1122 decrease to 0 if we are at a so-called group boundary. Here, a
1123 group is defined as the range of events that represent a single
1124 transaction in the relay log: see comment for is_in_group in
1125 rpl_rli.h for a definition.
1126
1127 The difficult part to implement is the logic to avoid decreasing
1128 the counter to 0. Given that groups have the form described in
1129 is_in_group in rpl_rli.h, we implement the logic as follows:
1130
1131 - Gtid, Rand, User_var, Int_var will never decrease the counter to
1132 0.
1133
1134 - BEGIN will set thd->variables.option_bits & OPTION_BEGIN and
1135 COMMIT/Xid will clear it. This happens regardless of whether
1136 the BEGIN/COMMIT/Xid is skipped itself.
1137
1138 - Other events will decrease the counter unless OPTION_BEGIN is
1139 set.
1140 */
1141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1567370 times.
1567368 DBUG_PRINT("info", ("ev->server_id=%lu, ::server_id=%lu,"
1142 " rli->replicate_same_server_id=%d,"
1143 " rli->slave_skip_counter=%d",
1144 (ulong)server_id, (ulong)::server_id,
1145 rli->replicate_same_server_id, rli->slave_skip_counter));
1146
6/6
✓ Branch 0 taken 38983 times.
✓ Branch 1 taken 1528387 times.
✓ Branch 2 taken 21424 times.
✓ Branch 3 taken 17559 times.
✓ Branch 4 taken 17856 times.
✓ Branch 5 taken 1549514 times.
3117181 if ((server_id == ::server_id && !rli->replicate_same_server_id) ||
1147
4/4
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 1549497 times.
✓ Branch 2 taken 297 times.
✓ Branch 3 taken 17 times.
1549811 (rli->slave_skip_counter == 1 && rli->is_in_group()))
1148 17856 return EVENT_SKIP_IGNORE;
1149
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 1549391 times.
1549514 else if (rli->slave_skip_counter > 0)
1150 123 return EVENT_SKIP_COUNT;
1151 else
1152 1549391 return EVENT_SKIP_NOT;
1153 }
1154
1155 /*
1156 Log_event::pack_info()
1157 */
1158
1159 10 int Log_event::pack_info(Protocol *protocol) {
1160 10 protocol->store("", &my_charset_bin);
1161 10 return 0;
1162 }
1163
1164
1/2
✓ Branch 0 taken 5279 times.
✗ Branch 1 not taken.
5279 const char *Log_event::get_db() { return thd ? thd->db().str : nullptr; }
1165
1166 /**
1167 Only called by SHOW BINLOG EVENTS
1168 */
1169 200998 int Log_event::net_send(Protocol *protocol, const char *log_name,
1170 my_off_t pos) {
1171 200998 const char *p = strrchr(log_name, FN_LIBCHAR);
1172 const char *event_type;
1173
2/2
✓ Branch 0 taken 200984 times.
✓ Branch 1 taken 14 times.
200998 if (p) log_name = p + 1;
1174
1175 200998 protocol->start_row();
1176 200998 protocol->store(log_name, &my_charset_bin);
1177 200998 protocol->store((ulonglong)pos);
1178 200998 event_type = get_type_str();
1179 200998 protocol->store_string(event_type, strlen(event_type), &my_charset_bin);
1180 200998 protocol->store((uint32)server_id);
1181 200998 protocol->store((ulonglong)common_header->log_pos);
1182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200998 times.
200998 if (pack_info(protocol)) return 1;
1183 200998 return protocol->end_row();
1184 }
1185
1186 /**
1187 init_show_field_list() prepares the column names and types for the
1188 output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG
1189 EVENTS.
1190 */
1191
1192 18049 void Log_event::init_show_field_list(mem_root_deque<Item *> *field_list) {
1193
3/6
✓ Branch 0 taken 18049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18049 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18049 times.
✗ Branch 5 not taken.
18049 field_list->push_back(new Item_empty_string("Log_name", 20));
1194
2/4
✓ Branch 0 taken 18049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18049 times.
✗ Branch 3 not taken.
36098 field_list->push_back(new Item_return_int("Pos", MY_INT32_NUM_DECIMAL_DIGITS,
1195
1/2
✓ Branch 0 taken 18049 times.
✗ Branch 1 not taken.
36098 MYSQL_TYPE_LONGLONG));
1196
3/6
✓ Branch 0 taken 18049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18049 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18049 times.
✗ Branch 5 not taken.
18049 field_list->push_back(new Item_empty_string("Event_type", 20));
1197
3/6
✓ Branch 0 taken 18049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18049 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18049 times.
✗ Branch 5 not taken.
18049 field_list->push_back(new Item_return_int("Server_id", 10, MYSQL_TYPE_LONG));
1198
2/4
✓ Branch 0 taken 18049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18049 times.
✗ Branch 3 not taken.
36098 field_list->push_back(new Item_return_int(
1199
1/2
✓ Branch 0 taken 18049 times.
✗ Branch 1 not taken.
36098 "End_log_pos", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG));
1200
3/6
✓ Branch 0 taken 18049 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18049 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18049 times.
✗ Branch 5 not taken.
18049 field_list->push_back(new Item_empty_string("Info", 20));
1201 18049 }
1202
1203 /**
1204 A decider of whether to trigger checksum computation or not.
1205 To be invoked in Log_event::write() stack.
1206 The decision is positive
1207
1208 S,M) if it's been marked for checksumming with @c checksum_alg
1209
1210 M) otherwise, if @@global.binlog_checksum is not NONE and the event is
1211 directly written to the binlog file.
1212 The to-be-cached event decides at @c write_cache() time.
1213
1214 Otherwise the decision is negative.
1215
1216 @note A side effect of the method is altering Log_event::checksum_alg
1217 it the latter was undefined at calling.
1218
1219 @return true (positive) or false (negative)
1220 */
1221 137579551 bool Log_event::need_checksum() {
1222
1/2
✓ Branch 0 taken 137586562 times.
✗ Branch 1 not taken.
137579551 DBUG_TRACE;
1223 137586562 bool ret = false;
1224 /*
1225 few callers of Log_event::write
1226 (incl FD::write, FD constructing code on the slave side, Rotate relay log
1227 and Stop event)
1228 provides their checksum alg preference through Log_event::checksum_alg.
1229 */
1230
2/2
✓ Branch 0 taken 120834741 times.
✓ Branch 1 taken 16751821 times.
137586562 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
1231 120834741 ret = (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF);
1232
1/2
✓ Branch 0 taken 16752061 times.
✗ Branch 1 not taken.
16751821 else if (binlog_checksum_options != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
1233
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 16752052 times.
16752061 event_cache_type == Log_event::EVENT_NO_CACHE)
1234 9 ret = (binlog_checksum_options != 0);
1235 else
1236 16751812 ret = false;
1237
1238 /*
1239 FD calls the methods before data_written has been calculated.
1240 The following invariant claims if the current is not the first
1241 call (and therefore data_written is not zero) then `ret' must be
1242 true. It may not be null because FD is always checksummed.
1243 */
1244
1245
5/6
✓ Branch 0 taken 429410 times.
✓ Branch 1 taken 137157172 times.
✓ Branch 2 taken 12609 times.
✓ Branch 3 taken 416801 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12609 times.
137586562 assert(get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT || ret ||
1246 common_header->data_written == 0);
1247
1248
2/2
✓ Branch 0 taken 16752852 times.
✓ Branch 1 taken 120833730 times.
137586582 if (common_footer->checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
1249 16752852 common_footer->checksum_alg =
1250
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 16752843 times.
16752852 ret ? // calculated value stored
1251 9 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options)
1252 : binary_log::BINLOG_CHECKSUM_ALG_OFF;
1253
1254
16/18
✓ Branch 0 taken 980038 times.
✓ Branch 1 taken 136606544 times.
✓ Branch 2 taken 911 times.
✓ Branch 3 taken 979127 times.
✓ Branch 4 taken 905 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 885 times.
✓ Branch 7 taken 20 times.
✓ Branch 8 taken 885 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 849 times.
✓ Branch 11 taken 36 times.
✓ Branch 12 taken 16 times.
✓ Branch 13 taken 833 times.
✓ Branch 14 taken 15 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 980037 times.
✗ Branch 17 not taken.
137586582 assert(
1255 !ret ||
1256 ((common_footer->checksum_alg ==
1257 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options) ||
1258 /*
1259 Stop event closes the relay-log and its checksum alg
1260 preference is set by the caller can be different
1261 from the server's binlog_checksum_options.
1262 */
1263 get_type_code() == binary_log::STOP_EVENT ||
1264 /*
1265 Rotate:s can be checksummed regardless of the server's
1266 binlog_checksum_options. That applies to both
1267 the local RL's Rotate and the master's Rotate
1268 which IO thread instantiates via queue_binlog_ver_3_event.
1269 */
1270 get_type_code() == binary_log::ROTATE_EVENT ||
1271 get_type_code() == binary_log::START_5_7_ENCRYPTION_EVENT ||
1272 /*
1273 The previous event has its checksum option defined
1274 according to the format description event.
1275 */
1276 get_type_code() == binary_log::PREVIOUS_GTIDS_LOG_EVENT ||
1277 /* FD is always checksummed */
1278 get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
1279 /*
1280 View_change_log_event is queued into relay log by the
1281 local member, which may have a different checksum algorithm
1282 than the one of the event source.
1283 */
1284 get_type_code() == binary_log::VIEW_CHANGE_EVENT) &&
1285 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF));
1286
1287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137586581 times.
137586581 assert(common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
1288
5/8
✓ Branch 0 taken 137369155 times.
✓ Branch 1 taken 217050 times.
✓ Branch 2 taken 137318903 times.
✓ Branch 3 taken 48897 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 266121 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
137586581 assert(((get_type_code() != binary_log::ROTATE_EVENT &&
1289 get_type_code() != binary_log::STOP_EVENT) ||
1290 get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT) ||
1291 event_cache_type == Log_event::EVENT_NO_CACHE);
1292
1293 137586745 return ret;
1294 137585024 }
1295
1296 87438364 bool Log_event::wrapper_my_b_safe_write(Basic_ostream *ostream,
1297 const uchar *buf, size_t size) {
1298
2/2
✓ Branch 0 taken 878059 times.
✓ Branch 1 taken 86560305 times.
87438364 if (size == 0) return false;
1299
1300
5/6
✓ Branch 0 taken 254937 times.
✓ Branch 1 taken 86308037 times.
✓ Branch 2 taken 254937 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 254937 times.
✓ Branch 5 taken 86308037 times.
86560305 if (need_checksum() && size != 0) crc = checksum_crc32(crc, buf, size);
1301
1302 86562974 return ostream->write(buf, size);
1303 }
1304
1305 16979996 bool Log_event::write_footer(Basic_ostream *ostream) {
1306 /*
1307 footer contains the checksum-algorithm descriptor
1308 followed by the checksum value
1309 */
1310
2/2
✓ Branch 0 taken 217268 times.
✓ Branch 1 taken 16762950 times.
16979996 if (need_checksum()) {
1311 uchar buf[BINLOG_CHECKSUM_LEN];
1312 217268 int4store(buf, crc);
1313
1/2
✓ Branch 0 taken 217268 times.
✗ Branch 1 not taken.
217268 return ostream->write((uchar *)buf, sizeof(buf));
1314 }
1315 16762950 return false;
1316 }
1317
1318 16979887 uint32 Log_event::write_header_to_memory(uchar *buf) {
1319 // Query start time
1320 16979887 ulong timestamp = (ulong)get_time();
1321
1322 #ifndef NDEBUG
1323
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 16979877 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16979877 times.
16979920 if (DBUG_EVALUATE_IF("inc_event_time_by_1_hour", 1, 0) &&
1324 DBUG_EVALUATE_IF("dec_event_time_by_1_hour", 1, 0)) {
1325 /**
1326 This assertion guarantees that these debug flags are not
1327 used at the same time (they would cancel each other).
1328 */
1329 assert(0);
1330 } else {
1331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16979721 times.
16979877 DBUG_EXECUTE_IF("inc_event_time_by_1_hour", timestamp = timestamp + 3600;);
1332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16979720 times.
16979721 DBUG_EXECUTE_IF("dec_event_time_by_1_hour", timestamp = timestamp - 3600;);
1333 }
1334 #endif
1335
1336 /*
1337 Header will be of size LOG_EVENT_HEADER_LEN for all events, except for
1338 FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT, where it will be
1339 LOG_EVENT_MINIMAL_HEADER_LEN (remember these 2 have a frozen header,
1340 because we read them before knowing the format).
1341 */
1342
1343 16979720 int4store(buf, timestamp);
1344 16979740 buf[EVENT_TYPE_OFFSET] = get_type_code();
1345 16979697 int4store(buf + SERVER_ID_OFFSET, server_id);
1346 16979775 int4store(buf + EVENT_LEN_OFFSET,
1347 16979775 static_cast<uint32>(common_header->data_written));
1348 16979776 int4store(buf + LOG_POS_OFFSET, static_cast<uint32>(common_header->log_pos));
1349 16979870 int2store(buf + FLAGS_OFFSET, common_header->flags);
1350
1351 16980041 return LOG_EVENT_HEADER_LEN;
1352 }
1353
1354 16979017 bool Log_event::write_header(Basic_ostream *ostream, size_t event_data_length) {
1355 uchar header[LOG_EVENT_HEADER_LEN];
1356 bool ret;
1357
1/2
✓ Branch 0 taken 16980036 times.
✗ Branch 1 not taken.
16979017 DBUG_TRACE;
1358
1359 /* Store number of bytes that will be written by this event */
1360 16980036 common_header->data_written = event_data_length + sizeof(header);
1361
1362
3/4
✓ Branch 0 taken 16980052 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 217280 times.
✓ Branch 3 taken 16762772 times.
16980036 if (need_checksum()) {
1363
1/2
✓ Branch 0 taken 217279 times.
✗ Branch 1 not taken.
217280 crc = checksum_crc32(0L, nullptr, 0);
1364 217279 common_header->data_written += BINLOG_CHECKSUM_LEN;
1365 }
1366
1367 /*
1368 Usually events are written into binlog cache first. And later, they are
1369 flushed into binlog file. When events are being written into binlog cache,
1370 log_pos(a.k.a. end_log_pos) field is meaningless. So it is set to 0. the
1371 log_pos field will be updated later when the events are being flushed into
1372 binlog file.
1373
1374 In a few cases(e.g. rotation(FD, Rotate events)), events are written into
1375 binlog file directly through event->write(). In these cases, log_pos is
1376 updated to the begin position of the event before calling event->write().
1377 Then log_pos is updated to the end position of the event here.
1378 */
1379
2/2
✓ Branch 0 taken 208438 times.
✓ Branch 1 taken 16771613 times.
16980051 if (common_header->log_pos != 0) {
1380 208438 common_header->log_pos += common_header->data_written;
1381 }
1382
1383
1/2
✓ Branch 0 taken 16980081 times.
✗ Branch 1 not taken.
16980051 write_header_to_memory(header);
1384
1385
1/2
✓ Branch 0 taken 16979505 times.
✗ Branch 1 not taken.
16980081 ret = ostream->write(header, LOG_EVENT_HEADER_LEN);
1386
1387 /*
1388 Update the checksum.
1389
1390 In case this is a Format_description_log_event, we need to clear
1391 the LOG_EVENT_BINLOG_IN_USE_F flag before computing the checksum,
1392 since the flag will be cleared when the binlog is closed. On
1393 verification, the flag is dropped before computing the checksum
1394 too.
1395 */
1396
5/6
✓ Branch 0 taken 16980253 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 217280 times.
✓ Branch 3 taken 16762973 times.
✓ Branch 4 taken 26099 times.
✓ Branch 5 taken 16954154 times.
17196785 if (need_checksum() &&
1397
2/2
✓ Branch 0 taken 26099 times.
✓ Branch 1 taken 191181 times.
217280 (common_header->flags & LOG_EVENT_BINLOG_IN_USE_F) != 0) {
1398 26099 common_header->flags &= ~LOG_EVENT_BINLOG_IN_USE_F;
1399 26099 int2store(header + FLAGS_OFFSET, common_header->flags);
1400 }
1401
1/2
✓ Branch 0 taken 16980561 times.
✗ Branch 1 not taken.
16980253 crc = my_checksum(crc, header, LOG_EVENT_HEADER_LEN);
1402
1403 16980233 return ret;
1404 16980561 }
1405 #endif /* MYSQL_SERVER */
1406
1407 69857797 bool Log_event::is_valid() {
1408
3/4
✓ Branch 0 taken 69858346 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69630389 times.
✓ Branch 3 taken 227970 times.
69857797 return common_header != nullptr && common_header->get_is_valid();
1409 }
1410
1411 #ifndef MYSQL_SERVER
1412
1413 /*
1414 Log_event::print_header()
1415 */
1416
1417 247454 void Log_event::print_header(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
1418 bool is_more [[maybe_unused]]) const {
1419 [[maybe_unused]] int write_res;
1420 char llbuff[22];
1421 247454 my_off_t hexdump_from = print_event_info->hexdump_from;
1422
1/2
✓ Branch 0 taken 247454 times.
✗ Branch 1 not taken.
247454 DBUG_TRACE;
1423
1424
1/2
✓ Branch 0 taken 247454 times.
✗ Branch 1 not taken.
247454 my_b_printf(file, "#");
1425
1/2
✓ Branch 0 taken 247454 times.
✗ Branch 1 not taken.
247454 print_timestamp(file, nullptr);
1426
1/2
✓ Branch 0 taken 247454 times.
✗ Branch 1 not taken.
247454 my_b_printf(file, " server id %lu end_log_pos %s ", (ulong)server_id,
1427
1/2
✓ Branch 0 taken 247454 times.
✗ Branch 1 not taken.
247454 llstr(common_header->log_pos, llbuff));
1428
1429 /* print the checksum */
1430
1431
2/2
✓ Branch 0 taken 246765 times.
✓ Branch 1 taken 689 times.
247454 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
1432
2/2
✓ Branch 0 taken 245830 times.
✓ Branch 1 taken 935 times.
246765 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF) {
1433 char checksum_buf[BINLOG_CHECKSUM_LEN * 2 + 4]; // to fit to "0x%lx "
1434 size_t const bytes_written =
1435 245830 snprintf(checksum_buf, sizeof(checksum_buf), "0x%08lx ", (ulong)crc);
1436
1/2
✓ Branch 0 taken 245830 times.
✗ Branch 1 not taken.
245830 my_b_printf(
1437 file, "%s ",
1438
1/2
✓ Branch 0 taken 245830 times.
✗ Branch 1 not taken.
245830 get_type(&binlog_checksum_typelib, common_footer->checksum_alg));
1439
1/2
✓ Branch 0 taken 245830 times.
✗ Branch 1 not taken.
245830 my_b_printf(file, checksum_buf, bytes_written);
1440 }
1441
1442 /* mysqlbinlog --hexdump */
1443
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 247118 times.
247454 if (print_event_info->hexdump_from) {
1444
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 my_b_printf(file, "\n");
1445 336 uchar *ptr = (uchar *)temp_buf;
1446 my_off_t size =
1447 336 uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN;
1448 my_off_t i;
1449
1450 /* Header len * 4 >= header len * (2 chars + space + extra space) */
1451 336 char *h, hex_string[49] = {0};
1452 336 char *c, char_string[16 + 1] = {0};
1453
1454 /* Pretty-print event common header if header is exactly 19 bytes */
1455
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN) {
1456 char emit_buf[256]; // Enough for storing one line
1457
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 my_b_printf(file,
1458 "# Position Timestamp Type Master ID "
1459 "Size Master Pos Flags \n");
1460 336 size_t const bytes_written = snprintf(
1461 emit_buf, sizeof(emit_buf),
1462 "# %8.8lx %02x %02x %02x %02x %02x "
1463 "%02x %02x %02x %02x %02x %02x %02x %02x "
1464 "%02x %02x %02x %02x %02x %02x\n",
1465 336 (unsigned long)hexdump_from, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4],
1466 336 ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12],
1467 336 ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
1468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1469
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 write_res = my_b_write(file, (uchar *)emit_buf, bytes_written);
1470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(write_res == 0);
1471 336 ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
1472 336 hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
1473 }
1474
1475 /* Rest of event (without common header) */
1476
2/2
✓ Branch 0 taken 424941 times.
✓ Branch 1 taken 336 times.
425277 for (i = 0, c = char_string, h = hex_string; i < size; i++, ptr++) {
1477
2/2
✓ Branch 0 taken 213196 times.
✓ Branch 1 taken 211745 times.
424941 snprintf(h, 4, (i % 16 <= 7) ? "%02x " : " %02x", *ptr);
1478 424941 h += 3;
1479
1480
2/2
✓ Branch 0 taken 319186 times.
✓ Branch 1 taken 105755 times.
424941 *c++ = my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.';
1481
1482
2/2
✓ Branch 0 taken 26367 times.
✓ Branch 1 taken 398574 times.
424941 if (i % 16 == 15) {
1483 /*
1484 my_b_printf() does not support full printf() formats, so we
1485 have to do it this way.
1486
1487 TODO: Rewrite my_b_printf() to support full printf() syntax.
1488 */
1489 char emit_buf[256];
1490 size_t const bytes_written =
1491 26367 snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %-48.48s |%16s|\n",
1492 26367 (unsigned long)(hexdump_from + (i & 0xfffffff0)),
1493 26367 hex_string, char_string);
1494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26367 times.
26367 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1495
1/2
✓ Branch 0 taken 26367 times.
✗ Branch 1 not taken.
26367 write_res = my_b_write(file, (uchar *)emit_buf, bytes_written);
1496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26367 times.
26367 assert(write_res == 0);
1497 26367 hex_string[0] = 0;
1498 26367 char_string[0] = 0;
1499 26367 c = char_string;
1500 26367 h = hex_string;
1501 }
1502 }
1503 336 *c = '\0';
1504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(hex_string[48] == 0);
1505
1506
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 12 times.
336 if (hex_string[0]) {
1507 char emit_buf[256];
1508 // Right-pad hex_string with spaces, up to 48 characters.
1509 324 memset(h, ' ', (sizeof(hex_string) - 1) - (h - hex_string));
1510 size_t const bytes_written =
1511 324 snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %-48.48s |%s|\n",
1512 324 (unsigned long)(hexdump_from + (i & 0xfffffff0)), hex_string,
1513 324 char_string);
1514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1515
1/2
✓ Branch 0 taken 324 times.
✗ Branch 1 not taken.
324 write_res = my_b_write(file, (uchar *)emit_buf, bytes_written);
1516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(write_res == 0);
1517 }
1518 /*
1519 need a # to prefix the rest of printouts for example those of
1520 Rows_log_event::print_helper().
1521 */
1522
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 write_res = my_b_write(file, reinterpret_cast<const uchar *>("# "), 2);
1523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
336 assert(write_res == 0);
1524 }
1525 247454 }
1526
1527 /**
1528 Auxiliary function that sets up a conversion table for m_b_write_quoted.
1529
1530 The table has 256 elements. The i'th element is 5 characters, the
1531 first being the length (1..4) and the remaining containing character
1532 #i quoted and not null-terminated. If character #i does not need
1533 quoting (it is >= 32 and not backslash or single-quote), the table
1534 only contains the character itself. A quoted character needs at
1535 most 4 bytes ("\xXX"), plus the length byte, so each element is 5
1536 bytes.
1537
1538 This function is called exactly once even in a multi-threaded
1539 environment, because it is only called in the initializer of a
1540 static variable.
1541
1542 @return Pointer to the table, a 256*5 character array where
1543 character i quoted .
1544 */
1545 2256 static const uchar *get_quote_table() {
1546 static uchar buf[256][5];
1547
2/2
✓ Branch 0 taken 577536 times.
✓ Branch 1 taken 2256 times.
579792 for (int i = 0; i < 256; i++) {
1548 char str[6];
1549
8/8
✓ Branch 0 taken 2256 times.
✓ Branch 1 taken 2256 times.
✓ Branch 2 taken 2256 times.
✓ Branch 3 taken 2256 times.
✓ Branch 4 taken 2256 times.
✓ Branch 5 taken 2256 times.
✓ Branch 6 taken 2256 times.
✓ Branch 7 taken 561744 times.
577536 switch (i) {
1550 2256 case '\b':
1551 2256 strcpy(str, "\\b");
1552 2256 break;
1553 2256 case '\f':
1554 2256 strcpy(str, "\\f");
1555 2256 break;
1556 2256 case '\n':
1557 2256 strcpy(str, "\\n");
1558 2256 break;
1559 2256 case '\r':
1560 2256 strcpy(str, "\\r");
1561 2256 break;
1562 2256 case '\t':
1563 2256 strcpy(str, "\\t");
1564 2256 break;
1565 2256 case '\\':
1566 2256 strcpy(str, "\\\\");
1567 2256 break;
1568 2256 case '\'':
1569 2256 strcpy(str, "\\'");
1570 2256 break;
1571 561744 default:
1572
2/2
✓ Branch 0 taken 60912 times.
✓ Branch 1 taken 500832 times.
561744 if (i < 32)
1573 60912 sprintf(str, "\\x%02x", i);
1574 else {
1575 500832 str[0] = i;
1576 500832 str[1] = '\0';
1577 }
1578 561744 break;
1579 }
1580 577536 buf[i][0] = strlen(str);
1581 577536 memcpy(buf[i] + 1, str, strlen(str));
1582 }
1583 2256 return (const uchar *)(buf);
1584 }
1585
1586 /**
1587 Prints a quoted string to io cache.
1588 Control characters are displayed as hex sequence, e.g. \x00
1589
1590 @param[in] file IO cache
1591 @param[in] ptr Pointer to string
1592 @param[in] length String length
1593
1594 @retval false Success
1595 @retval true Failure
1596 */
1597 28922 static bool my_b_write_quoted(IO_CACHE *file, const uchar *ptr, uint length) {
1598 [[maybe_unused]] int write_res;
1599 const uchar *s;
1600
3/4
✓ Branch 0 taken 2256 times.
✓ Branch 1 taken 26666 times.
✓ Branch 2 taken 2256 times.
✗ Branch 3 not taken.
28922 static const uchar *quote_table = get_quote_table();
1601 28922 my_b_printf(file, "'");
1602
2/2
✓ Branch 0 taken 635942079 times.
✓ Branch 1 taken 28922 times.
635971001 for (s = ptr; length > 0; s++, length--) {
1603 635942079 const uchar *len_and_str = quote_table + *s * 5;
1604 635942079 write_res = my_b_write(file, len_and_str + 1, len_and_str[0]);
1605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 635942079 times.
635942079 assert(write_res == 0);
1606 }
1607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28922 times.
28922 if (my_b_printf(file, "'") == (size_t)-1) return true;
1608 28922 return false;
1609 }
1610
1611 /**
1612 Prints a bit string to io cache in format b'1010'.
1613
1614 @param[in] file IO cache
1615 @param[in] ptr Pointer to string
1616 @param[in] nbits Number of bits
1617 */
1618 2676 static void my_b_write_bit(IO_CACHE *file, const uchar *ptr, uint nbits) {
1619 2676 uint bitnum, nbits8 = ((nbits + 7) / 8) * 8, skip_bits = nbits8 - nbits;
1620 2676 my_b_printf(file, "b'");
1621
2/2
✓ Branch 0 taken 54562 times.
✓ Branch 1 taken 2676 times.
57238 for (bitnum = skip_bits; bitnum < nbits8; bitnum++) {
1622 54562 int is_set = (ptr[(bitnum) / 8] >> (7 - bitnum % 8)) & 0x01;
1623 [[maybe_unused]]
1624
2/2
✓ Branch 0 taken 22128 times.
✓ Branch 1 taken 32434 times.
54562 int write_res = my_b_write(file, (const uchar *)(is_set ? "1" : "0"), 1);
1625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54562 times.
54562 assert(write_res == 0);
1626 }
1627 2676 my_b_printf(file, "'");
1628 2676 }
1629
1630 /**
1631 Prints a packed string to io cache.
1632 The string consists of length packed to 1 or 2 bytes,
1633 followed by string data itself.
1634
1635 @param[in] file IO cache
1636 @param[in] ptr Pointer to string
1637 @param[in] length String size
1638
1639 @retval - number of bytes scanned.
1640 */
1641 9517 static size_t my_b_write_quoted_with_length(IO_CACHE *file, const uchar *ptr,
1642 uint length) {
1643
2/2
✓ Branch 0 taken 6845 times.
✓ Branch 1 taken 2672 times.
9517 if (length < 256) {
1644 6845 length = *ptr;
1645 6845 my_b_write_quoted(file, ptr + 1, length);
1646 6845 return length + 1;
1647 } else {
1648 2672 length = uint2korr(ptr);
1649 2672 my_b_write_quoted(file, ptr + 2, length);
1650 2672 return length + 2;
1651 }
1652 }
1653
1654 /**
1655 Prints a 32-bit number in both signed and unsigned representation
1656
1657 @param[in] file IO cache
1658 @param[in] si Signed number
1659 @param[in] ui Unsigned number
1660 */
1661 17317 static void my_b_write_sint32_and_uint32(IO_CACHE *file, int32 si, uint32 ui) {
1662 17317 my_b_printf(file, "%d", si);
1663
2/2
✓ Branch 0 taken 6922 times.
✓ Branch 1 taken 10395 times.
17317 if (si < 0) my_b_printf(file, " (%u)", ui);
1664 17317 }
1665
1666 #ifndef MYSQL_SERVER
1667 2406 static const char *json_diff_operation_name(enum_json_diff_operation op,
1668 int last_path_char) {
1669
3/4
✓ Branch 0 taken 1686 times.
✓ Branch 1 taken 440 times.
✓ Branch 2 taken 280 times.
✗ Branch 3 not taken.
2406 switch (op) {
1670 1686 case enum_json_diff_operation::REPLACE:
1671 1686 return "JSON_REPLACE";
1672 440 case enum_json_diff_operation::INSERT:
1673
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 320 times.
440 if (last_path_char == ']')
1674 120 return "JSON_ARRAY_INSERT";
1675 else
1676 320 return "JSON_INSERT";
1677 280 case enum_json_diff_operation::REMOVE:
1678 280 return "JSON_REMOVE";
1679 }
1680 /* NOTREACHED */
1681 /* purecov: begin deadcode */
1682 assert(0);
1683 return nullptr;
1684 /* purecov: end */
1685 }
1686
1687 4911 static bool json_wrapper_to_string(IO_CACHE *out, String *buf,
1688 Json_wrapper *wrapper, bool json_type) {
1689
2/4
✓ Branch 0 taken 4911 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4911 times.
4911 if (wrapper->to_string(buf, false, "json_wrapper_to_string", [] {}))
1690 return true; /* purecov: inspected */ // OOM
1691
2/2
✓ Branch 0 taken 2809 times.
✓ Branch 1 taken 2102 times.
4911 if (json_type)
1692 2809 return my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1693
3/4
✓ Branch 0 taken 696 times.
✓ Branch 1 taken 1238 times.
✓ Branch 2 taken 168 times.
✗ Branch 3 not taken.
2102 switch (wrapper->type()) {
1694 696 case enum_json_type::J_NULL:
1695 case enum_json_type::J_DECIMAL:
1696 case enum_json_type::J_INT:
1697 case enum_json_type::J_UINT:
1698 case enum_json_type::J_DOUBLE:
1699 case enum_json_type::J_BOOLEAN:
1700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 696 times.
696 if (my_b_write(out, (uchar *)buf->ptr(), buf->length())) return true;
1701 696 break;
1702 1238 case enum_json_type::J_STRING:
1703 case enum_json_type::J_DATE:
1704 case enum_json_type::J_TIME:
1705 case enum_json_type::J_DATETIME:
1706 case enum_json_type::J_TIMESTAMP:
1707 case enum_json_type::J_OPAQUE:
1708 case enum_json_type::J_ERROR:
1709 1238 my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1710 1238 break;
1711 168 case enum_json_type::J_OBJECT:
1712 case enum_json_type::J_ARRAY:
1713 168 my_b_printf(out, "CAST(");
1714 168 my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1715 168 my_b_printf(out, " AS JSON)");
1716 168 break;
1717 default:
1718 assert(0); /* purecov: deadcode */
1719 }
1720 2102 return false;
1721 }
1722
1723 2258 static const char *print_json_diff(IO_CACHE *out, const uchar *data,
1724 size_t length, const char *col_name) {
1725
1/2
✓ Branch 0 taken 2258 times.
✗ Branch 1 not taken.
2258 DBUG_TRACE;
1726
1727 static const char *line_separator = "\n### ";
1728
1729 // read length
1730 2258 const uchar *p = data;
1731
1732 2258 const uchar *start_p = p;
1733 2258 size_t start_length = length;
1734
1735 // Read the list of operations.
1736 2258 std::vector<const char *> operation_names;
1737
2/2
✓ Branch 0 taken 2430 times.
✓ Branch 1 taken 2216 times.
4646 while (length) {
1738 // read operation
1739 2430 int operation_int = *p;
1740
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2424 times.
2430 if (operation_int >= JSON_DIFF_OPERATION_COUNT)
1741 42 return "reading operation type (invalid operation code)";
1742 2424 enum_json_diff_operation operation =
1743 static_cast<enum_json_diff_operation>(operation_int);
1744 2424 p++;
1745 2424 length--;
1746
1747 // skip path
1748 size_t path_length;
1749
3/4
✓ Branch 0 taken 2424 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 2412 times.
2424 if (net_field_length_checked<size_t>(&p, &length, &path_length))
1750 12 return "reading path length to skip";
1751
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2406 times.
2412 if (path_length > length) return "skipping path";
1752 2406 p += path_length;
1753 2406 length -= path_length;
1754
1755 // compute operation name
1756 2406 const char *operation_name = json_diff_operation_name(operation, p[-1]);
1757
1/2
✓ Branch 0 taken 2406 times.
✗ Branch 1 not taken.
2406 operation_names.push_back(operation_name);
1758
1759 // skip value
1760
2/2
✓ Branch 0 taken 2126 times.
✓ Branch 1 taken 280 times.
2406 if (operation != enum_json_diff_operation::REMOVE) {
1761 size_t value_length;
1762
3/4
✓ Branch 0 taken 2126 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 2114 times.
2126 if (net_field_length_checked<size_t>(&p, &length, &value_length))
1763 18 return "reading value length to skip";
1764
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2108 times.
2114 if (value_length > length) return "skipping value";
1765 2108 p += value_length;
1766 2108 length -= value_length;
1767 }
1768 }
1769
1770 // Print function names in reverse order.
1771 2216 bool printed = false;
1772
2/2
✓ Branch 0 taken 2388 times.
✓ Branch 1 taken 2216 times.
4604 for (int i = operation_names.size() - 1; i >= 0; i--) {
1773
6/6
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 1468 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 760 times.
✓ Branch 4 taken 1628 times.
✓ Branch 5 taken 760 times.
2388 if (i == 0 || operation_names[i - 1] != operation_names[i]) {
1774
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 1468 times.
1628 if (printed)
1775
2/4
✓ Branch 0 taken 160 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 160 times.
160 if (my_b_printf(out, "%s", line_separator) == (size_t)-1)
1776 return "printing line separator";
1777 /* purecov: inspected */ // error writing to output
1778
2/4
✓ Branch 0 taken 1628 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1628 times.
1628 if (my_b_printf(out, "%s(", operation_names[i]) == (size_t)-1)
1779 return "printing function name";
1780 /* purecov: inspected */ // error writing to output
1781 1628 printed = true;
1782 }
1783 }
1784
1785 // Print column id
1786
2/4
✓ Branch 0 taken 2216 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2216 times.
2216 if (my_b_printf(out, "%s", col_name) == (size_t)-1)
1787 return "printing column id";
1788 /* purecov: inspected */ // error writing to output
1789
1790 // In case this vector is empty (a no-op), make an early return
1791 // after printing only the column name
1792
2/2
✓ Branch 0 taken 748 times.
✓ Branch 1 taken 1468 times.
2216 if (operation_names.size() == 0) return nullptr;
1793
1794 // Print comma between column name and next function argument
1795
2/4
✓ Branch 0 taken 1468 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1468 times.
1468 if (my_b_printf(out, ", ") == (size_t)-1) return "printing comma";
1796 /* purecov: inspected */ // error writing to output
1797
1798 // Print paths and values.
1799 1468 p = start_p;
1800 1468 length = start_length;
1801 1468 StringBuffer<STRING_BUFFER_USUAL_SIZE> buf;
1802 1468 int diff_i = 0;
1803
2/2
✓ Branch 0 taken 2388 times.
✓ Branch 1 taken 1462 times.
3850 while (length) {
1804 // Read operation
1805 2388 enum_json_diff_operation operation = (enum_json_diff_operation)*p;
1806 2388 p++;
1807 2388 length--;
1808
1809 // Read path length
1810 size_t path_length;
1811
2/4
✓ Branch 0 taken 2388 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2388 times.
2388 if (net_field_length_checked<size_t>(&p, &length, &path_length))
1812 6 return "reading path length";
1813 /* purecov: deadcode */ // already checked in loop above
1814
1815 // Print path
1816
2/4
✓ Branch 0 taken 2388 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2388 times.
2388 if (my_b_write_quoted(out, p, path_length)) return "printing path";
1817 /* purecov: inspected */ // error writing to output
1818 2388 p += path_length;
1819 2388 length -= path_length;
1820
1821
2/2
✓ Branch 0 taken 2108 times.
✓ Branch 1 taken 280 times.
2388 if (operation != enum_json_diff_operation::REMOVE) {
1822 // Print comma between path and value
1823
2/4
✓ Branch 0 taken 2108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2108 times.
2114 if (my_b_printf(out, ", ") == (size_t)-1) return "printing comma";
1824 /* purecov: inspected */ // error writing to output
1825
1826 // Read value length
1827 size_t value_length;
1828
2/4
✓ Branch 0 taken 2108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2108 times.
2108 if (net_field_length_checked<size_t>(&p, &length, &value_length))
1829 return "reading value length";
1830 /* purecov: deadcode */ // already checked in loop above
1831
1832 // Read value
1833 json_binary::Value value =
1834
1/2
✓ Branch 0 taken 2108 times.
✗ Branch 1 not taken.
2108 json_binary::parse_binary((const char *)p, value_length);
1835 2108 p += value_length;
1836 2108 length -= value_length;
1837
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2102 times.
2108 if (value.type() == json_binary::Value::ERROR)
1838 6 return "parsing json value";
1839
1/2
✓ Branch 0 taken 2102 times.
✗ Branch 1 not taken.
2102 Json_wrapper wrapper(value);
1840
1841 // Print value
1842 2102 buf.length(0);
1843
2/4
✓ Branch 0 taken 2102 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2102 times.
2102 if (json_wrapper_to_string(out, &buf, &wrapper, false))
1844 return "converting json to string";
1845 /* purecov: inspected */ // OOM
1846 2102 buf.length(0);
1847
1/2
✓ Branch 0 taken 2102 times.
✗ Branch 1 not taken.
2102 }
1848
1849 // Print closing parenthesis
1850
6/6
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 1462 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 760 times.
✓ Branch 4 taken 1622 times.
✓ Branch 5 taken 760 times.
2382 if (length == 0 || operation_names[diff_i + 1] != operation_names[diff_i])
1851
2/4
✓ Branch 0 taken 1622 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1622 times.
1622 if (my_b_printf(out, ")") == (size_t)-1)
1852 return "printing closing parenthesis";
1853 /* purecov: inspected */ // error writing to output
1854
1855 // Print ending comma
1856
2/2
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 1462 times.
2382 if (length != 0)
1857
2/4
✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 920 times.
920 if (my_b_printf(out, ",%s", line_separator) == (size_t)-1)
1858 return "printing comma";
1859 /* purecov: inspected */ // error writing to output
1860
1861 2382 diff_i++;
1862 }
1863
1864 1462 return nullptr;
1865 2258 }
1866 #endif // ifndef MYSQL_SERVER
1867
1868 /**
1869 Print a packed value of the given SQL type into IO cache
1870
1871 @param[in] file IO cache
1872 @param[in] ptr Pointer to string
1873 @param[in] type Column type
1874 @param[in] meta Column meta information
1875 @param[out] typestr SQL type string buffer (for verbose output)
1876 @param[in] typestr_length Size of typestr
1877 @param[in] col_name Column name
1878 @param[in] is_partial True if this is a JSON column that will be
1879 read in partial format, false otherwise.
1880
1881 @retval 0 on error
1882 @retval number of bytes scanned from ptr for non-NULL fields, or
1883 another positive number for NULL fields
1884 */
1885 #ifndef MYSQL_SERVER
1886 66710 static size_t log_event_print_value(IO_CACHE *file, const uchar *ptr, uint type,
1887 uint meta, char *typestr,
1888 size_t typestr_length, char *col_name,
1889 bool is_partial) {
1890 66710 uint32 length = 0;
1891
1892
2/2
✓ Branch 0 taken 4854 times.
✓ Branch 1 taken 61856 times.
66710 if (type == MYSQL_TYPE_STRING) {
1893
1/2
✓ Branch 0 taken 4854 times.
✗ Branch 1 not taken.
4854 if (meta >= 256) {
1894 4854 uint byte0 = meta >> 8;
1895 4854 uint byte1 = meta & 0xFF;
1896
1897
2/2
✓ Branch 0 taken 148 times.
✓ Branch 1 taken 4706 times.
4854 if ((byte0 & 0x30) != 0x30) {
1898 /* a long CHAR() field: see #37426 */
1899 148 length = byte1 | (((byte0 & 0x30) ^ 0x30) << 4);
1900 148 type = byte0 | 0x30;
1901 } else
1902 4706 length = meta & 0xFF;
1903 } else
1904 length = meta;
1905 }
1906
1907
20/24
✓ Branch 0 taken 10201 times.
✓ Branch 1 taken 4744 times.
✓ Branch 2 taken 3182 times.
✓ Branch 3 taken 206 times.
✓ Branch 4 taken 3238 times.
✓ Branch 5 taken 3174 times.
✓ Branch 6 taken 3227 times.
✓ Branch 7 taken 3172 times.
✓ Branch 8 taken 1900 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1592 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1592 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1592 times.
✓ Branch 15 taken 1256 times.
✓ Branch 16 taken 812 times.
✓ Branch 17 taken 812 times.
✓ Branch 18 taken 824 times.
✓ Branch 19 taken 9856 times.
✓ Branch 20 taken 5179 times.
✓ Branch 21 taken 4854 times.
✓ Branch 22 taken 5297 times.
✗ Branch 23 not taken.
66710 switch (type) {
1908 10201 case MYSQL_TYPE_LONG: {
1909 10201 snprintf(typestr, typestr_length, "INT");
1910
2/2
✓ Branch 0 taken 856 times.
✓ Branch 1 taken 9345 times.
10201 if (!ptr) return my_b_printf(file, "NULL");
1911 9345 int32 si = sint4korr(ptr);
1912 9345 uint32 ui = uint4korr(ptr);
1913 9345 my_b_write_sint32_and_uint32(file, si, ui);
1914 9345 return 4;
1915 }
1916
1917 4744 case MYSQL_TYPE_TINY: {
1918 4744 snprintf(typestr, typestr_length, "TINYINT");
1919
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4680 times.
4744 if (!ptr) return my_b_printf(file, "NULL");
1920 4680 my_b_write_sint32_and_uint32(file, (int)(signed char)*ptr,
1921 4680 (uint)(unsigned char)*ptr);
1922 4680 return 1;
1923 }
1924
1925 3182 case MYSQL_TYPE_SHORT: {
1926 3182 snprintf(typestr, typestr_length, "SHORTINT");
1927
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3134 times.
3182 if (!ptr) return my_b_printf(file, "NULL");
1928 3134 int32 si = (int32)sint2korr(ptr);
1929 3134 uint32 ui = (uint32)uint2korr(ptr);
1930 3134 my_b_write_sint32_and_uint32(file, si, ui);
1931 3134 return 2;
1932 }
1933
1934 206 case MYSQL_TYPE_INT24: {
1935 206 snprintf(typestr, typestr_length, "MEDIUMINT");
1936
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 158 times.
206 if (!ptr) return my_b_printf(file, "NULL");
1937 158 int32 si = sint3korr(ptr);
1938 158 uint32 ui = uint3korr(ptr);
1939 158 my_b_write_sint32_and_uint32(file, si, ui);
1940 158 return 3;
1941 }
1942
1943 3238 case MYSQL_TYPE_LONGLONG: {
1944 3238 snprintf(typestr, typestr_length, "LONGINT");
1945
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3190 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
3238 if (!ptr) return my_b_printf(file, "NULL");
1946 char tmp[64];
1947 3190 longlong si = sint8korr(ptr);
1948
1/2
✓ Branch 0 taken 3190 times.
✗ Branch 1 not taken.
3190 longlong10_to_str(si, tmp, -10);
1949
1/2
✓ Branch 0 taken 3190 times.
✗ Branch 1 not taken.
3190 my_b_printf(file, "%s", tmp);
1950
2/2
✓ Branch 0 taken 1544 times.
✓ Branch 1 taken 1646 times.
3190 if (si < 0) {
1951 1544 ulonglong ui = uint8korr(ptr);
1952
1/2
✓ Branch 0 taken 1544 times.
✗ Branch 1 not taken.
1544 longlong10_to_str((longlong)ui, tmp, 10);
1953
1/2
✓ Branch 0 taken 1544 times.
✗ Branch 1 not taken.
1544 my_b_printf(file, " (%s)", tmp);
1954 }
1955 3190 return 8;
1956 }
1957
1958 3174 case MYSQL_TYPE_NEWDECIMAL: {
1959 3174 uint precision = meta >> 8;
1960 3174 uint decimals = meta & 0xFF;
1961 3174 snprintf(typestr, typestr_length, "DECIMAL(%d,%d)", precision, decimals);
1962
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3126 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
3174 if (!ptr) return my_b_printf(file, "NULL");
1963
1/2
✓ Branch 0 taken 3126 times.
✗ Branch 1 not taken.
3126 uint bin_size = my_decimal_get_binary_size(precision, decimals);
1964 3126 my_decimal dec;
1965
1/2
✓ Branch 0 taken 3126 times.
✗ Branch 1 not taken.
3126 binary2my_decimal(E_DEC_FATAL_ERROR, pointer_cast<const uchar *>(ptr),
1966 &dec, precision, decimals);
1967 char buff[DECIMAL_MAX_STR_LENGTH + 1];
1968 3126 int len = sizeof(buff);
1969
1/2
✓ Branch 0 taken 3126 times.
✗ Branch 1 not taken.
3126 decimal2string(&dec, buff, &len);
1970
1/2
✓ Branch 0 taken 3126 times.
✗ Branch 1 not taken.
3126 my_b_printf(file, "%s", buff);
1971 3126 return bin_size;
1972 3126 }
1973
1974 3227 case MYSQL_TYPE_FLOAT: {
1975 3227 snprintf(typestr, typestr_length, "FLOAT");
1976
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3179 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
3227 if (!ptr) return my_b_printf(file, "NULL");
1977 3179 float fl = float4get(ptr);
1978 char tmp[320];
1979 3179 sprintf(tmp, "%-20g", (double)fl);
1980
1/2
✓ Branch 0 taken 3179 times.
✗ Branch 1 not taken.
3179 my_b_printf(file, "%s", tmp); /* my_b_printf doesn't support %-20g */
1981 3179 return 4;
1982 }
1983
1984 3172 case MYSQL_TYPE_DOUBLE: {
1985 3172 strcpy(typestr, "DOUBLE");
1986
3/4
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3124 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
3172 if (!ptr) return my_b_printf(file, "NULL");
1987 3124 double dbl = float8get(ptr);
1988 char tmp[320];
1989 3124 sprintf(tmp, "%-.20g", dbl); /* my_b_printf doesn't support %-20g */
1990
1/2
✓ Branch 0 taken 3124 times.
✗ Branch 1 not taken.
3124 my_b_printf(file, "%s", tmp);
1991 3124 return 8;
1992 }
1993
1994 1900 case MYSQL_TYPE_BIT: {
1995 /* Meta-data: bit_len, bytes_in_rec, 2 bytes */
1996 1900 uint nbits = ((meta >> 8) * 8) + (meta & 0xFF);
1997 1900 snprintf(typestr, typestr_length, "BIT(%d)", nbits);
1998
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1868 times.
1900 if (!ptr) return my_b_printf(file, "NULL");
1999 1868 length = (nbits + 7) / 8;
2000 1868 my_b_write_bit(file, ptr, nbits);
2001 1868 return length;
2002 }
2003
2004 case MYSQL_TYPE_TIMESTAMP: {
2005 snprintf(typestr, typestr_length, "TIMESTAMP");
2006 if (!ptr) return my_b_printf(file, "NULL");
2007 uint32 i32 = uint4korr(ptr);
2008 my_b_printf(file, "%d", i32);
2009 return 4;
2010 }
2011
2012 1592 case MYSQL_TYPE_TIMESTAMP2: {
2013 1592 snprintf(typestr, typestr_length, "TIMESTAMP(%d)", meta);
2014
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
1592 if (!ptr) return my_b_printf(file, "NULL");
2015 char buf[MAX_DATE_STRING_REP_LENGTH];
2016 my_timeval tm;
2017
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 my_timestamp_from_binary(&tm, ptr, meta);
2018
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 int buflen = my_timeval_to_str(&tm, buf, meta);
2019
2/4
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1576 times.
1576 if (my_b_write(file, pointer_cast<uchar *>(buf), buflen)) return 0;
2020
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 return my_timestamp_binary_length(meta);
2021 }
2022
2023 case MYSQL_TYPE_DATETIME: {
2024 snprintf(typestr, typestr_length, "DATETIME");
2025 if (!ptr) return my_b_printf(file, "NULL");
2026 size_t d, t;
2027 uint64 i64 = uint8korr(ptr); /* YYYYMMDDhhmmss */
2028 d = static_cast<size_t>(i64 / 1000000);
2029 t = i64 % 1000000;
2030 my_b_printf(file, "%04d-%02d-%02d %02d:%02d:%02d",
2031 static_cast<int>(d / 10000),
2032 static_cast<int>(d % 10000) / 100, static_cast<int>(d % 100),
2033 static_cast<int>(t / 10000),
2034 static_cast<int>(t % 10000) / 100, static_cast<int>(t % 100));
2035 return 8;
2036 }
2037
2038 1592 case MYSQL_TYPE_DATETIME2: {
2039 1592 snprintf(typestr, typestr_length, "DATETIME(%d)", meta);
2040
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
1592 if (!ptr) return my_b_printf(file, "NULL");
2041 char buf[MAX_DATE_STRING_REP_LENGTH];
2042 MYSQL_TIME ltime;
2043
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 longlong packed = my_datetime_packed_from_binary(ptr, meta);
2044
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 TIME_from_longlong_datetime_packed(&ltime, packed);
2045
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 int buflen = my_datetime_to_str(ltime, buf, meta);
2046
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 my_b_write_quoted(file, (uchar *)buf, buflen);
2047
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 return my_datetime_binary_length(meta);
2048 }
2049
2050 case MYSQL_TYPE_TIME: {
2051 snprintf(typestr, typestr_length, "TIME");
2052 if (!ptr) return my_b_printf(file, "NULL");
2053 uint32 i32 = uint3korr(ptr);
2054 my_b_printf(file, "'%02d:%02d:%02d'", i32 / 10000, (i32 % 10000) / 100,
2055 i32 % 100);
2056 return 3;
2057 }
2058
2059 1592 case MYSQL_TYPE_TIME2: {
2060 1592 snprintf(typestr, typestr_length, "TIME(%d)", meta);
2061
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
1592 if (!ptr) return my_b_printf(file, "NULL");
2062 char buf[MAX_DATE_STRING_REP_LENGTH];
2063 MYSQL_TIME ltime;
2064
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 longlong packed = my_time_packed_from_binary(ptr, meta);
2065
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 TIME_from_longlong_time_packed(&ltime, packed);
2066
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 int buflen = my_time_to_str(ltime, buf, meta);
2067
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 my_b_write_quoted(file, (uchar *)buf, buflen);
2068
1/2
✓ Branch 0 taken 1576 times.
✗ Branch 1 not taken.
1576 return my_time_binary_length(meta);
2069 }
2070
2071 1256 case MYSQL_TYPE_NEWDATE: {
2072 1256 snprintf(typestr, typestr_length, "DATE");
2073
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1240 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
1256 if (!ptr) return my_b_printf(file, "NULL");
2074 1240 uint32 tmp = uint3korr(ptr);
2075 int part;
2076 char buf[11];
2077 1240 char *pos = &buf[10]; // start from '\0' to the beginning
2078
2079 /* Copied from field.cc */
2080 1240 *pos-- = 0; // End NULL
2081 1240 part = (int)(tmp & 31);
2082 1240 *pos-- = (char)('0' + part % 10);
2083 1240 *pos-- = (char)('0' + part / 10);
2084 1240 *pos-- = ':';
2085 1240 part = (int)(tmp >> 5 & 15);
2086 1240 *pos-- = (char)('0' + part % 10);
2087 1240 *pos-- = (char)('0' + part / 10);
2088 1240 *pos-- = ':';
2089 1240 part = (int)(tmp >> 9);
2090 1240 *pos-- = (char)('0' + part % 10);
2091 1240 part /= 10;
2092 1240 *pos-- = (char)('0' + part % 10);
2093 1240 part /= 10;
2094 1240 *pos-- = (char)('0' + part % 10);
2095 1240 part /= 10;
2096 1240 *pos = (char)('0' + part);
2097
1/2
✓ Branch 0 taken 1240 times.
✗ Branch 1 not taken.
1240 my_b_printf(file, "'%s'", buf);
2098 1240 return 3;
2099 }
2100
2101 812 case MYSQL_TYPE_YEAR: {
2102 812 snprintf(typestr, typestr_length, "YEAR");
2103
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 796 times.
812 if (!ptr) return my_b_printf(file, "NULL");
2104 796 uint32 i32 = *ptr;
2105 796 my_b_printf(file, "%04d", i32 + 1900);
2106 796 return 1;
2107 }
2108
2109 812 case MYSQL_TYPE_ENUM:
2110
1/3
✓ Branch 0 taken 812 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
812 switch (meta & 0xFF) {
2111 812 case 1:
2112 812 snprintf(typestr, typestr_length, "ENUM(1 byte)");
2113
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 796 times.
812 if (!ptr) return my_b_printf(file, "NULL");
2114 796 my_b_printf(file, "%d", (int)*ptr);
2115 796 return 1;
2116 case 2: {
2117 snprintf(typestr, typestr_length, "ENUM(2 bytes)");
2118 if (!ptr) return my_b_printf(file, "NULL");
2119 int32 i32 = uint2korr(ptr);
2120 my_b_printf(file, "%d", i32);
2121 return 2;
2122 }
2123 default:
2124 my_b_printf(file, "!! Unknown ENUM packlen=%d", meta & 0xFF);
2125 return 0;
2126 }
2127 break;
2128
2129 824 case MYSQL_TYPE_SET:
2130 824 snprintf(typestr, typestr_length, "SET(%d bytes)", meta & 0xFF);
2131
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 808 times.
824 if (!ptr) return my_b_printf(file, "NULL");
2132 808 my_b_write_bit(file, ptr, (meta & 0xFF) * 8);
2133 808 return meta & 0xFF;
2134
2135 9856 case MYSQL_TYPE_BLOB:
2136
4/5
✓ Branch 0 taken 3684 times.
✓ Branch 1 taken 2255 times.
✓ Branch 2 taken 1948 times.
✓ Branch 3 taken 1969 times.
✗ Branch 4 not taken.
9856 switch (meta) {
2137 3684 case 1:
2138 3684 snprintf(typestr, typestr_length, "TINYBLOB/TINYTEXT");
2139
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 3636 times.
3684 if (!ptr) return my_b_printf(file, "NULL");
2140 3636 length = *ptr;
2141 3636 my_b_write_quoted(file, ptr + 1, length);
2142 3636 return length + 1;
2143 2255 case 2:
2144 2255 snprintf(typestr, typestr_length, "BLOB/TEXT");
2145
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 2193 times.
2255 if (!ptr) return my_b_printf(file, "NULL");
2146 2193 length = uint2korr(ptr);
2147 2193 my_b_write_quoted(file, ptr + 2, length);
2148 2193 return length + 2;
2149 1948 case 3:
2150 1948 snprintf(typestr, typestr_length, "MEDIUMBLOB/MEDIUMTEXT");
2151
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1900 times.
1948 if (!ptr) return my_b_printf(file, "NULL");
2152 1900 length = uint3korr(ptr);
2153 1900 my_b_write_quoted(file, ptr + 3, length);
2154 1900 return length + 3;
2155 1969 case 4:
2156 1969 snprintf(typestr, typestr_length, "LONGBLOB/LONGTEXT");
2157
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1921 times.
1969 if (!ptr) return my_b_printf(file, "NULL");
2158 1921 length = uint4korr(ptr);
2159 1921 my_b_write_quoted(file, ptr + 4, length);
2160 1921 return length + 4;
2161 default:
2162 my_b_printf(file, "!! Unknown BLOB packlen=%d", length);
2163 return 0;
2164 }
2165
2166 5179 case MYSQL_TYPE_VARCHAR:
2167 case MYSQL_TYPE_VAR_STRING:
2168 5179 length = meta;
2169 5179 snprintf(typestr, typestr_length, "VARSTRING(%d)", length);
2170
2/2
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 4919 times.
5179 if (!ptr) return my_b_printf(file, "NULL");
2171 4919 return my_b_write_quoted_with_length(file, ptr, length);
2172
2173 4854 case MYSQL_TYPE_STRING:
2174 4854 snprintf(typestr, typestr_length, "STRING(%d)", length);
2175
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 4598 times.
4854 if (!ptr) return my_b_printf(file, "NULL");
2176 4598 return my_b_write_quoted_with_length(file, ptr, length);
2177
2178 5297 case MYSQL_TYPE_JSON: {
2179 5297 snprintf(typestr, typestr_length, "JSON");
2180
2/2
✓ Branch 0 taken 230 times.
✓ Branch 1 taken 5067 times.
5297 if (!ptr) return my_b_printf(file, "NULL");
2181 5067 length = uint4korr(ptr);
2182 5067 ptr += 4;
2183
2/2
✓ Branch 0 taken 2258 times.
✓ Branch 1 taken 2809 times.
5067 if (is_partial) {
2184 2258 const char *error = print_json_diff(file, ptr, length, col_name);
2185
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2210 times.
2258 if (error != nullptr)
2186 48 my_b_printf(file, "Error %s while printing JSON diff\n", error);
2187 } else {
2188 json_binary::Value value =
2189
1/2
✓ Branch 0 taken 2809 times.
✗ Branch 1 not taken.
2809 json_binary::parse_binary((const char *)ptr, length);
2190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2809 times.
2809 if (value.type() == json_binary::Value::ERROR) {
2191 if (my_b_printf(
2192 file,
2193 "Invalid JSON\n")) /* purecov: inspected */ // corrupted
2194 // event
2195 return 0; /* purecov: inspected */ // error writing output
2196 } else {
2197
1/2
✓ Branch 0 taken 2809 times.
✗ Branch 1 not taken.
2809 Json_wrapper wrapper(value);
2198 2809 StringBuffer<STRING_BUFFER_USUAL_SIZE> s;
2199
2/4
✓ Branch 0 taken 2809 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2809 times.
2809 if (json_wrapper_to_string(file, &s, &wrapper, true))
2200 my_b_printf(file, "Failed to format JSON object as string.\n");
2201 /* purecov: inspected */ // OOM
2202 2809 }
2203 }
2204 5067 return length + meta;
2205 }
2206 case MYSQL_TYPE_BOOL:
2207 case MYSQL_TYPE_INVALID:
2208 default: {
2209 char tmp[5];
2210 snprintf(tmp, sizeof(tmp), "%04x", meta);
2211 my_b_printf(file,
2212 "!! Don't know how to handle column type=%d meta=%d (%s)\n",
2213 type, meta, tmp);
2214 } break;
2215 }
2216 *typestr = 0;
2217 return 0;
2218 }
2219 #endif
2220
2221 /**
2222 Print a packed row into IO cache
2223
2224 @param[in] file IO cache
2225 @param[in] td Table definition
2226 @param[in] print_event_info Print parameters
2227 @param[in] cols_bitmap Column bitmaps.
2228 @param[in] value Pointer to packed row
2229 @param[in] prefix Row's SQL clause ("SET", "WHERE", etc)
2230
2231 @retval - number of bytes scanned.
2232 */
2233
2234 7179 size_t Rows_log_event::print_verbose_one_row(
2235 IO_CACHE *file, table_def *td, PRINT_EVENT_INFO *print_event_info,
2236 MY_BITMAP *cols_bitmap, const uchar *value, const uchar *prefix,
2237 enum_row_image_type row_image_type) {
2238 7179 const uchar *value0 = value;
2239 7179 char typestr[64] = "";
2240
2241 // Read value_options if this is AI for PARTIAL_UPDATE_ROWS_EVENT
2242 7179 ulonglong value_options = 0;
2243
1/2
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
7179 Bit_reader partial_bits;
2244
6/6
✓ Branch 0 taken 5230 times.
✓ Branch 1 taken 1949 times.
✓ Branch 2 taken 2615 times.
✓ Branch 3 taken 2615 times.
✓ Branch 4 taken 2615 times.
✓ Branch 5 taken 4564 times.
7179 if (get_type_code() == binary_log::PARTIAL_UPDATE_ROWS_EVENT &&
2245 row_image_type == enum_row_image_type::UPDATE_AI) {
2246 2615 size_t length = m_rows_end - value;
2247
2/4
✓ Branch 0 taken 2615 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2615 times.
2615 if (net_field_length_checked<ulonglong>(&value, &length, &value_options)) {
2248 my_b_printf(file,
2249 "*** Error reading binlog_row_value_options from "
2250 "Partial_update_rows_log_event\n");
2251 return 0;
2252 }
2253
2/2
✓ Branch 0 taken 1850 times.
✓ Branch 1 taken 765 times.
2615 if ((value_options & PARTIAL_JSON_UPDATES) != 0) {
2254 1850 partial_bits.set_ptr(value);
2255
1/2
✓ Branch 0 taken 1850 times.
✗ Branch 1 not taken.
1850 value += (td->json_column_count() + 7) / 8;
2256 }
2257 }
2258
2259 /*
2260 Metadata bytes which gives the information about nullabity of
2261 master columns. Master writes one bit for each column in the
2262 image.
2263 */
2264
1/2
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
7179 Bit_reader null_bits(value);
2265
1/2
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
7179 value += (bitmap_bits_set(cols_bitmap) + 7) / 8;
2266
2267
1/2
✓ Branch 0 taken 7179 times.
✗ Branch 1 not taken.
7179 my_b_printf(file, "%s", prefix);
2268
2269
2/2
✓ Branch 0 taken 83288 times.
✓ Branch 1 taken 7179 times.
90467 for (size_t i = 0; i < td->size(); i++) {
2270 /*
2271 Note: need to read partial bit before reading cols_bitmap, since
2272 the partial_bits bitmap has a bit for every JSON column
2273 regardless of whether it is included in the bitmap or not.
2274 */
2275
1/2
✓ Branch 0 taken 34968 times.
✗ Branch 1 not taken.
34968 bool is_partial = (value_options & PARTIAL_JSON_UPDATES) != 0 &&
2276
2/2
✓ Branch 0 taken 2478 times.
✓ Branch 1 taken 32490 times.
34968 row_image_type == enum_row_image_type::UPDATE_AI &&
2277
4/4
✓ Branch 0 taken 34968 times.
✓ Branch 1 taken 48320 times.
✓ Branch 2 taken 2258 times.
✓ Branch 3 taken 220 times.
153224 td->type(i) == MYSQL_TYPE_JSON && partial_bits.get();
2278
2279
2/2
✓ Branch 0 taken 16578 times.
✓ Branch 1 taken 66710 times.
83288 if (bitmap_is_set(cols_bitmap, i) == 0) continue;
2280
2281 66710 bool is_null = null_bits.get();
2282
2283
1/2
✓ Branch 0 taken 66710 times.
✗ Branch 1 not taken.
66710 my_b_printf(file, "### @%d=", static_cast<int>(i + 1));
2284
2/2
✓ Branch 0 taken 64406 times.
✓ Branch 1 taken 2304 times.
66710 if (!is_null) {
2285 size_t fsize =
2286
1/2
✓ Branch 0 taken 64406 times.
✗ Branch 1 not taken.
64406 td->calc_field_size((uint)i, pointer_cast<const uchar *>(value));
2287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64406 times.
64406 if (fsize > (size_t)(m_rows_end - value)) {
2288 my_b_printf(file,
2289 "***Corrupted replication event was detected: "
2290 "field size is set to %u, but there are only %u bytes "
2291 "left of the event. Not printing the value***\n",
2292 (uint)fsize, (uint)(m_rows_end - value));
2293 return 0;
2294 }
2295 }
2296 char col_name[256];
2297 66710 sprintf(col_name, "@%lu", (unsigned long)i + 1);
2298
3/4
✓ Branch 0 taken 2304 times.
✓ Branch 1 taken 64406 times.
✓ Branch 2 taken 66710 times.
✗ Branch 3 not taken.
133420 size_t size = log_event_print_value(
2299 66710 file, is_null ? nullptr : value, td->type(i), td->field_metadata(i),
2300 typestr, sizeof(typestr), col_name, is_partial);
2301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66710 times.
66710 if (!size) return 0;
2302
2303
2/2
✓ Branch 0 taken 64406 times.
✓ Branch 1 taken 2304 times.
66710 if (!is_null) value += size;
2304
2305
2/2
✓ Branch 0 taken 7624 times.
✓ Branch 1 taken 59086 times.
66710 if (print_event_info->verbose > 1) {
2306
1/2
✓ Branch 0 taken 7624 times.
✗ Branch 1 not taken.
7624 my_b_printf(file, " /* ");
2307
2308
1/2
✓ Branch 0 taken 7624 times.
✗ Branch 1 not taken.
7624 my_b_printf(file, "%s ", typestr);
2309
2310
1/2
✓ Branch 0 taken 7624 times.
✗ Branch 1 not taken.
7624 my_b_printf(file, "meta=%d nullable=%d is_null=%d ",
2311 7624 td->field_metadata(i), td->maybe_null(i), is_null);
2312
1/2
✓ Branch 0 taken 7624 times.
✗ Branch 1 not taken.
7624 my_b_printf(file, "*/");
2313 }
2314
2315
1/2
✓ Branch 0 taken 66710 times.
✗ Branch 1 not taken.
66710 my_b_printf(file, "\n");
2316 }
2317 7179 return value - value0;
2318 }
2319
2320 /**
2321 Print a row event into IO cache in human readable form (in SQL format)
2322
2323 @param[in] file IO cache
2324 @param[in] print_event_info Print parameters
2325 */
2326 3355 void Rows_log_event::print_verbose(IO_CACHE *file,
2327 PRINT_EVENT_INFO *print_event_info) {
2328 // Quoted length of the identifier can be twice the original length
2329 char quoted_db[1 + NAME_LEN * 2 + 2];
2330 char quoted_table[1 + NAME_LEN * 2 + 2];
2331 size_t quoted_db_len, quoted_table_len;
2332 Table_map_log_event *map;
2333 table_def *td;
2334 const char *sql_command, *sql_clause1, *sql_clause2;
2335
1/2
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
3355 Log_event_type general_type_code = get_general_type_code();
2336
2337 enum_row_image_type row_image_type =
2338
1/2
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
3355 get_general_type_code() == binary_log::WRITE_ROWS_EVENT
2339
2/2
✓ Branch 0 taken 2818 times.
✓ Branch 1 taken 537 times.
6173 ? enum_row_image_type::WRITE_AI
2340
1/2
✓ Branch 0 taken 2818 times.
✗ Branch 1 not taken.
2818 : get_general_type_code() == binary_log::DELETE_ROWS_EVENT
2341
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 2563 times.
2818 ? enum_row_image_type::DELETE_BI
2342 3355 : enum_row_image_type::UPDATE_BI;
2343
2344
4/4
✓ Branch 0 taken 3339 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 3338 times.
6694 if (m_extra_row_info.have_ndb_info() ||
2345
3/4
✓ Branch 0 taken 3339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3338 times.
3339 DBUG_EVALUATE_IF("simulate_error_in_ndb_info_print", 1, 0)) {
2346 int extra_row_ndb_info_payload_len =
2347
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 m_extra_row_info.get_ndb_length() - EXTRA_ROW_INFO_HEADER_LENGTH;
2348
2349
3/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 16 times.
17 if (m_extra_row_info.get_ndb_length() < EXTRA_ROW_INFO_HEADER_LENGTH) {
2350
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_b_printf(file,
2351 "***Error: The number of extra_row_ndb_info is smaller"
2352 " than the minimum acceptable value.\n");
2353 1 return;
2354 }
2355 16 unsigned char *ndb_info = m_extra_row_info.get_ndb_info();
2356 16 my_b_printf(file, "### Extra row ndb info: data_format: %u, len: %u, ",
2357
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 ndb_info[EXTRA_ROW_INFO_FORMAT_OFFSET],
2358 extra_row_ndb_info_payload_len);
2359 /*
2360 Buffer for hex view of string, including '0x' prefix,
2361 2 hex chars / byte and trailing 0
2362 */
2363 16 const int buff_len = 2 + (256 * 2) + 1;
2364 char buff[buff_len];
2365
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 str_to_hex(buff, (const char *)&(ndb_info[EXTRA_ROW_INFO_HEADER_LENGTH]),
2366 extra_row_ndb_info_payload_len);
2367
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_b_printf(file, "data: %s\n", buff);
2368 }
2369
2370
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 3249 times.
3354 if (m_extra_row_info.have_part()) {
2371
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 73 times.
105 if (general_type_code == binary_log::UPDATE_ROWS_EVENT) {
2372
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 my_b_printf(file,
2373 "### Extra row info for partitioning: source_partition: %d"
2374 " target_partition: %d",
2375 32 m_extra_row_info.get_source_partition_id(),
2376 32 m_extra_row_info.get_partition_id());
2377 } else
2378
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 my_b_printf(file, "### Extra row info for partitioning: partition: %u",
2379 73 m_extra_row_info.get_partition_id());
2380
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 my_b_printf(file, "\n");
2381 }
2382
2383
3/4
✓ Branch 0 taken 536 times.
✓ Branch 1 taken 255 times.
✓ Branch 2 taken 2563 times.
✗ Branch 3 not taken.
3354 switch (general_type_code) {
2384 536 case binary_log::WRITE_ROWS_EVENT:
2385 536 sql_command = "INSERT INTO";
2386 536 sql_clause1 = "### SET\n";
2387 536 sql_clause2 = nullptr;
2388 536 break;
2389 255 case binary_log::DELETE_ROWS_EVENT:
2390 255 sql_command = "DELETE FROM";
2391 255 sql_clause1 = "### WHERE\n";
2392 255 sql_clause2 = nullptr;
2393 255 break;
2394 2563 case binary_log::UPDATE_ROWS_EVENT:
2395 case binary_log::PARTIAL_UPDATE_ROWS_EVENT:
2396 2563 sql_command = "UPDATE";
2397 2563 sql_clause1 = "### WHERE\n";
2398 2563 sql_clause2 = "### SET\n";
2399 2563 break;
2400 default:
2401 sql_command = sql_clause1 = sql_clause2 = nullptr;
2402 assert(0); /* Not possible */
2403 }
2404
2405
3/6
✓ Branch 0 taken 3354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3354 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3354 times.
6708 if (!(map = print_event_info->m_table_map.get_table(m_table_id)) ||
2406
2/4
✓ Branch 0 taken 3354 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3354 times.
3354 !(td = map->create_table_def())) {
2407 char llbuff[22];
2408 my_b_printf(file, "### Row event for unknown table #%s",
2409 llstr(m_table_id, llbuff));
2410 return;
2411 }
2412
2413 /* If the write rows event contained no values for the AI */
2414
2/2
✓ Branch 0 taken 536 times.
✓ Branch 1 taken 2818 times.
3354 if (((general_type_code == binary_log::WRITE_ROWS_EVENT) &&
2415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 536 times.
536 (m_rows_buf == m_rows_end))) {
2416 my_b_printf(file, "### INSERT INTO `%s`.`%s` VALUES ()\n",
2417 map->get_db_name(), map->get_table_name());
2418 goto end;
2419 }
2420
2421
2/2
✓ Branch 0 taken 4239 times.
✓ Branch 1 taken 3354 times.
7593 for (const uchar *value = m_rows_buf; value < m_rows_end;) {
2422 size_t length;
2423 quoted_db_len =
2424
1/2
✓ Branch 0 taken 4239 times.
✗ Branch 1 not taken.
4239 my_strmov_quoted_identifier((char *)quoted_db, map->get_db_name());
2425
1/2
✓ Branch 0 taken 4239 times.
✗ Branch 1 not taken.
4239 quoted_table_len = my_strmov_quoted_identifier((char *)quoted_table,
2426 map->get_table_name());
2427 4239 quoted_db[quoted_db_len] = '\0';
2428 4239 quoted_table[quoted_table_len] = '\0';
2429
1/2
✓ Branch 0 taken 4239 times.
✗ Branch 1 not taken.
4239 my_b_printf(file, "### %s %s.%s\n", sql_command, quoted_db, quoted_table);
2430 /* Print the first image */
2431
2/4
✓ Branch 0 taken 4239 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4239 times.
4239 if (!(length = print_verbose_one_row(file, td, print_event_info, &m_cols,
2432 value, (const uchar *)sql_clause1,
2433 row_image_type)))
2434 goto end;
2435 4239 value += length;
2436
2437 /* Print the second image (for UPDATE only) */
2438
2/2
✓ Branch 0 taken 2940 times.
✓ Branch 1 taken 1299 times.
4239 if (sql_clause2) {
2439
2/4
✓ Branch 0 taken 2940 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2940 times.
2940 if (!(length = print_verbose_one_row(
2440 file, td, print_event_info, &m_cols_ai, value,
2441 (const uchar *)sql_clause2, enum_row_image_type::UPDATE_AI)))
2442 goto end;
2443 2940 value += length;
2444 }
2445 }
2446
2447 3354 end:
2448
1/2
✓ Branch 0 taken 3354 times.
✗ Branch 1 not taken.
3354 delete td;
2449 }
2450
2451 77075 void Log_event::print_base64(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
2452 bool more) const {
2453 77075 const uchar *ptr = (const uchar *)temp_buf;
2454 77075 uint32 size = uint4korr(ptr + EVENT_LEN_OFFSET);
2455
1/2
✓ Branch 0 taken 77075 times.
✗ Branch 1 not taken.
77075 DBUG_TRACE;
2456
2457 77075 uint64 const tmp_str_sz = base64_needed_encoded_length((uint64)size);
2458 char *const tmp_str =
2459
1/2
✓ Branch 0 taken 77075 times.
✗ Branch 1 not taken.
77075 (char *)my_malloc(key_memory_log_event, tmp_str_sz, MYF(MY_WME));
2460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77075 times.
77075 if (!tmp_str) {
2461 fprintf(stderr,
2462 "\nError: Out of memory. "
2463 "Could not print correct binlog event.\n");
2464 return;
2465 }
2466
2467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77075 times.
77075 if (base64_encode(ptr, (size_t)size, tmp_str)) {
2468 assert(0);
2469 }
2470
2471
2/2
✓ Branch 0 taken 75925 times.
✓ Branch 1 taken 1150 times.
77075 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS) {
2472
3/4
✓ Branch 0 taken 35425 times.
✓ Branch 1 taken 40500 times.
✓ Branch 2 taken 35425 times.
✗ Branch 3 not taken.
75925 if (my_b_tell(file) == 0) my_b_printf(file, "\nBINLOG '\n");
2473
2474
1/2
✓ Branch 0 taken 75925 times.
✗ Branch 1 not taken.
75925 my_b_printf(file, "%s\n", tmp_str);
2475
2476
3/4
✓ Branch 0 taken 40084 times.
✓ Branch 1 taken 35841 times.
✓ Branch 2 taken 40084 times.
✗ Branch 3 not taken.
75925 if (!more) my_b_printf(file, "'%s\n", print_event_info->delimiter);
2477 }
2478
2479
2/2
✓ Branch 0 taken 9408 times.
✓ Branch 1 taken 67667 times.
77075 if (print_event_info->verbose) {
2480 9408 Rows_log_event *ev = nullptr;
2481 9408 Log_event_type et = (Log_event_type)ptr[EVENT_TYPE_OFFSET];
2482
2483 9408 enum_binlog_checksum_alg ev_checksum_alg = common_footer->checksum_alg;
2484 Format_description_event fd_evt =
2485
1/2
✓ Branch 0 taken 9408 times.
✗ Branch 1 not taken.
9408 Format_description_event(BINLOG_VERSION, server_version);
2486 9408 fd_evt.footer()->checksum_alg = ev_checksum_alg;
2487
2488
5/5
✓ Branch 0 taken 3306 times.
✓ Branch 1 taken 537 times.
✓ Branch 2 taken 255 times.
✓ Branch 3 taken 2563 times.
✓ Branch 4 taken 2747 times.
9408 switch (et) {
2489 3306 case binary_log::TABLE_MAP_EVENT: {
2490 Table_map_log_event *map;
2491
2/4
✓ Branch 0 taken 3306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3306 times.
✗ Branch 3 not taken.
3306 map = new Table_map_log_event((const char *)ptr, &fd_evt);
2492
1/2
✓ Branch 0 taken 3306 times.
✗ Branch 1 not taken.
3306 print_event_info->m_table_map.set_table(map->get_table_id(), map);
2493 3306 break;
2494 }
2495 537 case binary_log::WRITE_ROWS_EVENT:
2496 case binary_log::WRITE_ROWS_EVENT_V1: {
2497
2/4
✓ Branch 0 taken 537 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 537 times.
✗ Branch 3 not taken.
537 ev = new Write_rows_log_event((const char *)ptr, &fd_evt);
2498 537 break;
2499 }
2500 255 case binary_log::DELETE_ROWS_EVENT:
2501 case binary_log::DELETE_ROWS_EVENT_V1: {
2502
2/4
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 255 times.
✗ Branch 3 not taken.
255 ev = new Delete_rows_log_event((const char *)ptr, &fd_evt);
2503 255 break;
2504 }
2505 2563 case binary_log::UPDATE_ROWS_EVENT:
2506 case binary_log::UPDATE_ROWS_EVENT_V1:
2507 case binary_log::PARTIAL_UPDATE_ROWS_EVENT: {
2508
2/4
✓ Branch 0 taken 2563 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2563 times.
✗ Branch 3 not taken.
2563 ev = new Update_rows_log_event((const char *)ptr, &fd_evt);
2509 2563 break;
2510 }
2511 2747 default:
2512 2747 break;
2513 }
2514
2515
2/2
✓ Branch 0 taken 3355 times.
✓ Branch 1 taken 6053 times.
9408 if (ev) {
2516
1/2
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
3355 ev->print_verbose(&print_event_info->footer_cache, print_event_info);
2517
1/2
✓ Branch 0 taken 3355 times.
✗ Branch 1 not taken.
3355 delete ev;
2518 }
2519 9408 }
2520
2521
1/2
✓ Branch 0 taken 77075 times.
✗ Branch 1 not taken.
77075 my_free(tmp_str);
2522
1/2
✓ Branch 0 taken 77075 times.
✗ Branch 1 not taken.
77075 }
2523
2524 /*
2525 Log_event::print_timestamp()
2526 */
2527
2528 252201 void Log_event::print_timestamp(IO_CACHE *file, time_t *ts) const {
2529 struct tm *res;
2530 /*
2531 In some Windows versions timeval.tv_sec is defined as "long",
2532 not as "time_t" and can be of a different size.
2533 Let's use a temporary time_t variable to execute localtime()
2534 with a correct argument type.
2535 */
2536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 252201 times.
252201 time_t ts_tmp = ts ? *ts : (ulong)common_header->when.tv_sec;
2537
1/2
✓ Branch 0 taken 252201 times.
✗ Branch 1 not taken.
252201 DBUG_TRACE;
2538 struct tm tm_tmp;
2539 252201 localtime_r(&ts_tmp, (res = &tm_tmp));
2540 252201 my_b_printf(file, "%02d%02d%02d %2d:%02d:%02d", res->tm_year % 100,
2541
1/2
✓ Branch 0 taken 252201 times.
✗ Branch 1 not taken.
252201 res->tm_mon + 1, res->tm_mday, res->tm_hour, res->tm_min,
2542 res->tm_sec);
2543 252201 }
2544
2545 #endif /* !MYSQL_SERVER */
2546
2547 #if defined(MYSQL_SERVER)
2548 577097 inline Log_event::enum_skip_reason Log_event::continue_group(
2549 Relay_log_info *rli) {
2550
2/2
✓ Branch 0 taken 811 times.
✓ Branch 1 taken 576286 times.
577097 if (rli->slave_skip_counter == 1) return Log_event::EVENT_SKIP_IGNORE;
2551 576286 return Log_event::do_shall_skip(rli);
2552 }
2553
2554 /**
2555 @param end_group_sets_max_dbs when true the group terminal event
2556 can carry partition info, see a note below.
2557 @return true in cases the current event
2558 carries partition data,
2559 false otherwise
2560
2561 @note Some events combination may force to adjust partition info.
2562 In particular BEGIN, BEGIN_LOAD_QUERY_EVENT, COMMIT
2563 where none of the events holds partitioning data
2564 causes the sequential applying of the group through
2565 assigning OVER_MAX_DBS_IN_EVENT_MTS to mts_accessed_dbs
2566 of the group terminator (e.g COMMIT query) event.
2567 */
2568 1577 bool Log_event::contains_partition_info(bool end_group_sets_max_dbs) {
2569 bool res;
2570
2571
3/3
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 790 times.
✓ Branch 2 taken 533 times.
1577 switch (get_type_code()) {
2572 254 case binary_log::TABLE_MAP_EVENT:
2573 case binary_log::EXECUTE_LOAD_QUERY_EVENT:
2574 case binary_log::TRANSACTION_PAYLOAD_EVENT:
2575 254 res = true;
2576
2577 254 break;
2578
2579 790 case binary_log::QUERY_EVENT: {
2580 790 Query_log_event *qev = static_cast<Query_log_event *>(this);
2581
8/8
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 699 times.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 781 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 780 times.
2355 if ((ends_group() && end_group_sets_max_dbs) ||
2582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 780 times.
1565 (qev->is_query_prefix_match(STRING_WITH_LEN("XA COMMIT")) ||
2583 781 qev->is_query_prefix_match(STRING_WITH_LEN("XA ROLLBACK")))) {
2584 10 res = true;
2585 10 qev->mts_accessed_dbs = OVER_MAX_DBS_IN_EVENT_MTS;
2586 } else
2587
4/4
✓ Branch 0 taken 694 times.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 492 times.
✓ Branch 3 taken 202 times.
780 res = (!ends_group() && !starts_group()) ? true : false;
2588 790 break;
2589 }
2590 533 default:
2591 533 res = false;
2592 }
2593
2594 1577 return res;
2595 }
2596 /*
2597 SYNOPSIS
2598 This function assigns a parent ID to the job group being scheduled in
2599 parallel. It also checks if we can schedule the new event in parallel with the
2600 previous ones being executed.
2601
2602 @param ev log event that has to be scheduled next.
2603 @param rli Pointer to coordinator's relay log info.
2604 @return true if error
2605 false otherwise
2606 */
2607 282288 static bool schedule_next_event(Log_event *ev, Relay_log_info *rli) {
2608 int error;
2609 // Check if we can schedule this event
2610 282288 error = rli->current_mts_submode->schedule_next_event(rli, ev);
2611
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 51 times.
✓ Branch 3 taken 282218 times.
282276 switch (error) {
2612 char llbuff[22];
2613 1 case ER_MTS_CANT_PARALLEL:
2614
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 llstr(rli->get_event_relay_log_pos(), llbuff);
2615
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_error(ER_MTS_CANT_PARALLEL, MYF(0), ev->get_type_str(),
2616 rli->get_event_relay_log_name(), llbuff,
2617 "The master event is logically timestamped incorrectly.");
2618 1 return true;
2619 6 case ER_MTS_INCONSISTENT_DATA:
2620
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 llstr(rli->get_event_relay_log_pos(), llbuff);
2621 {
2622 6 char errfmt[] =
2623 "Coordinator experienced an error or was killed while scheduling "
2624 "an event at relay-log name %s position %s.";
2625 char errbuf[sizeof(errfmt) + FN_REFLEN + sizeof(llbuff)];
2626 6 sprintf(errbuf, errfmt, rli->get_event_relay_log_name(), llbuff);
2627
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_error(ER_MTS_INCONSISTENT_DATA, MYF(0), errbuf);
2628 6 return true;
2629 }
2630 /* Don't have to do anything. */
2631 return true;
2632 51 case -1:
2633 /* Unable to schedule: wait_for_last_committed_trx has failed */
2634 51 return true;
2635 282218 default:
2636 282218 return false;
2637 }
2638 /* Keep compiler happy */
2639 return false;
2640 }
2641
2642 /**
2643 The method maps the event to a Worker and return a pointer to it.
2644 Sending the event to the Worker is done by the caller.
2645
2646 Irrespective of the type of Group marking (DB partitioned or BGC) the
2647 following holds true:
2648
2649 - recognize the beginning of a group to allocate the group descriptor
2650 and queue it;
2651 - associate an event with a Worker (which also handles possible conflicts
2652 detection and waiting for their termination);
2653 - finalize the group assignment when the group closing event is met.
2654
2655 When parallelization mode is BGC-based the partitioning info in the event
2656 is simply ignored. Thereby association with a Worker does not require
2657 Assigned Partition Hash of the partitioned method.
2658 This method is not interested in all the taxonomy of the event group
2659 property, what we care about is the boundaries of the group.
2660
2661 As a part of the group, an event belongs to one of the following types:
2662
2663 B - beginning of a group of events (BEGIN query_log_event)
2664 g - mini-group representative event containing the partition info
2665 (any Table_map, a Query_log_event)
2666 p - a mini-group internal event that *p*receding its g-parent
2667 (int_, rand_, user_ var:s)
2668 r - a mini-group internal "regular" event that follows its g-parent
2669 (Delete, Update, Write -rows)
2670 T - terminator of the group (XID, COMMIT, ROLLBACK, auto-commit query)
2671
2672 Only the first g-event computes the assigned Worker which once
2673 is determined remains to be for the rest of the group.
2674 That is the g-event solely carries partitioning info.
2675 For B-event the assigned Worker is NULL to indicate Coordinator
2676 has not yet decided. The same applies to p-event.
2677
2678 Notice, these is a special group consisting of optionally multiple p-events
2679 terminating with a g-event.
2680 Such case is caused by old master binlog and a few corner-cases of
2681 the current master version (todo: to fix).
2682
2683 In case of the event accesses more than OVER_MAX_DBS the method
2684 has to ensure sure previously assigned groups to all other workers are
2685 done.
2686
2687
2688 @note The function updates GAQ queue directly, updates APH hash
2689 plus relocates some temporary tables from Coordinator's list into
2690 involved entries of APH through @c map_db_to_worker.
2691 There's few memory allocations commented where to be freed.
2692
2693 @return a pointer to the Worker struct or NULL.
2694 */
2695
2696 1511055 Slave_worker *Log_event::get_slave_worker(Relay_log_info *rli) {
2697 1511055 Slave_job_group group = Slave_job_group(), *ptr_group = nullptr;
2698 bool is_s_event;
2699 1511053 Slave_worker *ret_worker = nullptr;
2700 char llbuff[22];
2701 1511053 Slave_committed_queue *gaq = rli->gaq;
2702
1/2
✓ Branch 0 taken 1511055 times.
✗ Branch 1 not taken.
1511053 DBUG_TRACE;
2703
2704 /* checking partitioning properties and perform corresponding actions */
2705
2706 // Beginning of a group designated explicitly with BEGIN or GTID
2707
7/8
✓ Branch 0 taken 1511055 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1262638 times.
✓ Branch 3 taken 248417 times.
✓ Branch 4 taken 980479 times.
✓ Branch 5 taken 282159 times.
✓ Branch 6 taken 530705 times.
✓ Branch 7 taken 980350 times.
2491534 if ((is_s_event = starts_group()) || is_gtid_event(this) ||
2708 // or DDL:s or autocommit queries possibly associated with own p-events
2709
4/4
✓ Branch 0 taken 33783 times.
✓ Branch 1 taken 946696 times.
✓ Branch 2 taken 129 times.
✓ Branch 3 taken 33654 times.
980479 (!rli->curr_group_seen_begin && !rli->curr_group_seen_gtid &&
2710 /*
2711 the following is a special case of B-free still multi-event group like
2712 { p_1,p_2,...,p_k, g }.
2713 In that case either GAQ is empty (the very first group is being
2714 assigned) or the last assigned group index points at one of
2715 mapped-to-a-worker.
2716 */
2717
3/4
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✓ Branch 3 taken 9 times.
129 (gaq->empty() ||
2718
2/4
✓ Branch 0 taken 120 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 gaq->get_job_group(rli->gaq->assigned_group_index)->worker_id !=
2719 MTS_WORKER_UNDEF))) {
2720
3/4
✓ Branch 0 taken 282288 times.
✓ Branch 1 taken 248417 times.
✓ Branch 2 taken 282288 times.
✗ Branch 3 not taken.
530705 if (!rli->curr_group_seen_gtid && !rli->curr_group_seen_begin) {
2721 282288 rli->mts_groups_assigned++;
2722
2723 282288 rli->curr_group_isolated = false;
2724 282288 group.reset(common_header->log_pos, rli->mts_groups_assigned);
2725 // the last occupied GAQ's array index
2726
1/2
✓ Branch 0 taken 282288 times.
✗ Branch 1 not taken.
282288 gaq->assigned_group_index = gaq->en_queue(&group);
2727
3/8
✓ Branch 0 taken 282288 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 282288 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 282288 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
282288 DBUG_PRINT("info", ("gaq_idx= %ld gaq->size=%zu",
2728 gaq->assigned_group_index, gaq->capacity));
2729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282288 times.
282288 assert(gaq->assigned_group_index != MTS_WORKER_UNDEF);
2730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282288 times.
282288 assert(gaq->assigned_group_index < gaq->capacity);
2731
2/4
✓ Branch 0 taken 282288 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 282288 times.
282288 assert(gaq->get_job_group(rli->gaq->assigned_group_index)
2732 ->group_relay_log_name == nullptr);
2733
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 282288 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
282288 assert(rli->last_assigned_worker == nullptr ||
2734 !is_mts_db_partitioned(rli));
2735
2736
6/6
✓ Branch 0 taken 282287 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 282158 times.
✓ Branch 3 taken 129 times.
✓ Branch 4 taken 282159 times.
✓ Branch 5 taken 129 times.
282288 if (is_s_event || is_gtid_event(this)) {
2737 282159 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2738 282159 rli->get_event_start_pos()};
2739 // B-event is appended to the Deferred Array associated with GCAP
2740
1/2
✓ Branch 0 taken 282159 times.
✗ Branch 1 not taken.
282159 rli->curr_group_da.push_back(job_item);
2741
2742
2/4
✓ Branch 0 taken 282159 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 282159 times.
282159 assert(rli->curr_group_da.size() == 1);
2743
2744
2/4
✓ Branch 0 taken 282159 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 282159 times.
282159 if (starts_group()) {
2745 // mark the current group as started with explicit B-event
2746 rli->mts_end_group_sets_max_dbs = true;
2747 rli->curr_group_seen_begin = true;
2748 }
2749
2750
1/2
✓ Branch 0 taken 282159 times.
✗ Branch 1 not taken.
282159 if (is_gtid_event(this)) {
2751 // mark the current group as started with explicit Gtid-event
2752 282159 rli->curr_group_seen_gtid = true;
2753
2754 282159 Gtid_log_event *gtid_log_ev = static_cast<Gtid_log_event *>(this);
2755
1/2
✓ Branch 0 taken 282159 times.
✗ Branch 1 not taken.
282159 rli->started_processing(gtid_log_ev);
2756 }
2757
2758
3/4
✓ Branch 0 taken 282147 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 282091 times.
282159 if (schedule_next_event(this, rli)) {
2759 56 rli->abort_slave = true;
2760
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 if (is_gtid_event(this)) {
2761
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 rli->clear_processing_trx();
2762 }
2763 56 return nullptr;
2764 }
2765 282091 return ret_worker;
2766 }
2767 129 } else {
2768 /*
2769 The block is a result of not making GTID event as group starter.
2770 TODO: Make GITD event as B-event that is starts_group() to
2771 return true.
2772 */
2773 248417 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2774 248417 rli->get_event_relay_log_pos()};
2775
2776 // B-event is appended to the Deferred Array associated with GCAP
2777
1/2
✓ Branch 0 taken 248415 times.
✗ Branch 1 not taken.
248416 rli->curr_group_da.push_back(job_item);
2778 248415 rli->curr_group_seen_begin = true;
2779 248415 rli->mts_end_group_sets_max_dbs = true;
2780
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 248415 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 248415 times.
248415 if (!rli->curr_group_seen_gtid && schedule_next_event(this, rli)) {
2781 rli->abort_slave = true;
2782 return nullptr;
2783 }
2784
2785
2/4
✓ Branch 0 taken 248415 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 248415 times.
248415 assert(rli->curr_group_da.size() == 2);
2786
2/4
✓ Branch 0 taken 248415 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 248415 times.
248415 assert(starts_group());
2787 248415 return ret_worker;
2788 }
2789
3/4
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 127 times.
129 if (schedule_next_event(this, rli)) {
2790 2 rli->abort_slave = true;
2791 2 return nullptr;
2792 }
2793 }
2794
2795
1/2
✓ Branch 0 taken 980477 times.
✗ Branch 1 not taken.
980477 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2796
3/4
✓ Branch 0 taken 980477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 979847 times.
✓ Branch 3 taken 630 times.
980477 if (!is_mts_db_partitioned(rli)) {
2797 /* Get least occupied worker */
2798
1/2
✓ Branch 0 taken 979847 times.
✗ Branch 1 not taken.
979847 ret_worker = rli->current_mts_submode->get_least_occupied_worker(
2799 rli, &rli->workers, this);
2800
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 979845 times.
979847 if (ret_worker == nullptr) {
2801 /* get_least_occupied_worker may return NULL if the thread is killed */
2802 2 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2803 2 rli->get_event_start_pos()};
2804
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->curr_group_da.push_back(job_item);
2805
2806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(thd->killed);
2807 2 return nullptr;
2808 }
2809 979845 ptr_group->worker_id = ret_worker->id;
2810
3/4
✓ Branch 0 taken 630 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 289 times.
630 } else if (contains_partition_info(rli->mts_end_group_sets_max_dbs)) {
2811 341 int i = 0;
2812 341 Mts_db_names mts_dbs;
2813
2814
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 get_mts_dbs(&mts_dbs, rli->rpl_filter);
2815 /*
2816 Bug 12982188 - MTS: SBR ABORTS WITH ERROR 1742 ON LOAD DATA
2817 Logging on master can create a group with no events holding
2818 the partition info.
2819 The following assert proves there's the only reason
2820 for such group.
2821 */
2822 #ifndef NDEBUG
2823 {
2824 563 bool empty_group_with_gtids = rli->curr_group_seen_begin &&
2825
6/8
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 119 times.
✓ Branch 2 taken 222 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 222 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 219 times.
341 rli->curr_group_seen_gtid && ends_group();
2826
2827 bool begin_load_query_event =
2828
2/4
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
344 ((rli->curr_group_da.size() == 3 && rli->curr_group_seen_gtid) ||
2829
7/10
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 338 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 176 times.
✓ Branch 5 taken 162 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 176 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
344 (rli->curr_group_da.size() == 2 && !rli->curr_group_seen_gtid)) &&
2830
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (rli->curr_group_da.back().data->get_type_code() ==
2831 341 binary_log::BEGIN_LOAD_QUERY_EVENT);
2832
2833 bool delete_file_event =
2834
1/4
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
341 ((rli->curr_group_da.size() == 4 && rli->curr_group_seen_gtid) ||
2835
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 338 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
341 (rli->curr_group_da.size() == 3 && !rli->curr_group_seen_gtid)) &&
2836 (rli->curr_group_da.back().data->get_type_code() ==
2837 341 binary_log::DELETE_FILE_EVENT);
2838
2839
8/18
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 334 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
341 assert((!ends_group() ||
2840 (get_type_code() == binary_log::TRANSACTION_PAYLOAD_EVENT) ||
2841 (get_type_code() == binary_log::QUERY_EVENT &&
2842 static_cast<Query_log_event *>(this)->is_query_prefix_match(
2843 STRING_WITH_LEN("XA ROLLBACK")))) ||
2844 empty_group_with_gtids ||
2845 (rli->mts_end_group_sets_max_dbs &&
2846 (begin_load_query_event || delete_file_event)));
2847 }
2848 #endif
2849
2850 // partitioning info is found which drops the flag
2851 341 rli->mts_end_group_sets_max_dbs = false;
2852 341 ret_worker = rli->last_assigned_worker;
2853
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 313 times.
341 if (mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS) {
2854 // Worker with id 0 to handle serial execution
2855
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 if (!ret_worker) ret_worker = rli->workers.at(0);
2856 // No need to know a possible error out of synchronization call.
2857
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 (void)rli->current_mts_submode->wait_for_workers_to_finish(rli,
2858 ret_worker);
2859 /*
2860 this marking is transferred further into T-event of the current group.
2861 */
2862 28 rli->curr_group_isolated = true;
2863 }
2864 #ifndef NDEBUG
2865 {
2866
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 std::ostringstream oss;
2867 682 for (i = 0;
2868
4/4
✓ Branch 0 taken 626 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 341 times.
682 i < ((mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS) ? mts_dbs.num : 1);
2869 i++) {
2870
2/2
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 28 times.
341 if (mts_dbs.name[i] != nullptr) {
2871
2/4
✓ Branch 0 taken 313 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 313 times.
✗ Branch 3 not taken.
313 oss << mts_dbs.name[i] << ", ";
2872 }
2873 }
2874
3/12
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 341 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
341 DBUG_PRINT("debug", ("ASSIGN %p %s", current_thd, oss.str().c_str()));
2875 341 }
2876 #endif
2877
2878 /* One run of the loop in the case of over-max-db:s */
2879 682 for (i = 0;
2880
4/4
✓ Branch 0 taken 626 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 341 times.
✓ Branch 3 taken 341 times.
682 i < ((mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS) ? mts_dbs.num : 1);
2881 i++) {
2882 /*
2883 The over max db:s case handled through passing to map_db_to_worker
2884 such "all" db as encoded as the "" empty string.
2885 Note, the empty string is allocated in a large buffer
2886 to satisfy hashcmp() implementation.
2887 */
2888 341 const char all_db[NAME_LEN] = {0};
2889
2/4
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 341 times.
341 if (!(ret_worker = map_db_to_worker(
2890
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 313 times.
341 mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS ? all_db
2891 : mts_dbs.name[i],
2892 rli, &mts_assigned_partitions[i],
2893 /*
2894 todo: optimize it. Although pure
2895 rows- event load in insensitive to the flag value
2896 */
2897 true, ret_worker))) {
2898 llstr(rli->get_event_relay_log_pos(), llbuff);
2899 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
2900 rli->get_event_relay_log_name(), llbuff,
2901 "could not distribute the event to a Worker");
2902 return ret_worker;
2903 }
2904 // all temporary tables are transferred from Coordinator in over-max case
2905
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 313 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
341 assert(mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS ||
2906 !thd->temporary_tables);
2907
3/4
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 341 times.
341 assert(!strcmp(
2908 mts_assigned_partitions[i]->db,
2909 mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS ? mts_dbs.name[i] : all_db));
2910
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 assert(ret_worker == mts_assigned_partitions[i]->worker);
2911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 assert(mts_assigned_partitions[i]->usage >= 0);
2912 }
2913
2914
1/2
✓ Branch 0 taken 341 times.
✗ Branch 1 not taken.
341 if ((ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index))
2915
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 49 times.
341 ->worker_id == MTS_WORKER_UNDEF) {
2916 292 ptr_group->worker_id = ret_worker->id;
2917
2918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 292 times.
292 assert(ptr_group->group_relay_log_name == nullptr);
2919 }
2920
2921
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 313 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
341 assert(i == mts_dbs.num || mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS);
2922 } else {
2923 // a mini-group internal "regular" event
2924
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 9 times.
289 if (rli->last_assigned_worker) {
2925 280 ret_worker = rli->last_assigned_worker;
2926
2927
2/6
✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 280 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
280 assert(rli->curr_group_assigned_parts.size() > 0 || ret_worker->id == 0);
2928 } else // int_, rand_, user_ var:s, load-data events
2929 {
2930
4/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
25 if (!(get_type_code() == binary_log::INTVAR_EVENT ||
2931
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
16 get_type_code() == binary_log::RAND_EVENT ||
2932
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
10 get_type_code() == binary_log::USER_VAR_EVENT ||
2933
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 get_type_code() == binary_log::BEGIN_LOAD_QUERY_EVENT ||
2934
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 get_type_code() == binary_log::APPEND_BLOCK_EVENT ||
2935 3 get_type_code() == binary_log::DELETE_FILE_EVENT ||
2936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 is_ignorable_event())) {
2937 assert(!ret_worker);
2938
2939 llstr(rli->get_event_relay_log_pos(), llbuff);
2940 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
2941 rli->get_event_relay_log_name(), llbuff,
2942 "the event is a part of a group that is unsupported in "
2943 "the parallel execution mode");
2944
2945 return ret_worker;
2946 }
2947 /*
2948 In the logical clock scheduler any internal gets scheduled directly.
2949 That is Int_var, @User_var and Rand bypass the deferred array.
2950 Their association with relay-log physical coordinates is provided
2951 by the same mechanism that applies to a regular event.
2952 */
2953 9 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2954 9 rli->get_event_start_pos()};
2955
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 rli->curr_group_da.push_back(job_item);
2956
2957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(!ret_worker);
2958 9 return ret_worker;
2959 }
2960 }
2961
2962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 980466 times.
980466 assert(ret_worker);
2963 // T-event: Commit, Xid, a DDL query or dml query of B-less group.4
2964
2965 /*
2966 Preparing event physical coordinates info for Worker before any
2967 event got scheduled so when Worker error-stopped at the first
2968 event it would be aware of where exactly in the event stream.
2969 */
2970
2/2
✓ Branch 0 taken 30767 times.
✓ Branch 1 taken 949699 times.
980466 if (!ret_worker->master_log_change_notified) {
2971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30767 times.
30767 if (!ptr_group)
2972 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2973
1/2
✓ Branch 0 taken 30767 times.
✗ Branch 1 not taken.
30767 ptr_group->group_master_log_name = my_strdup(
2974 key_memory_log_event, rli->get_group_master_log_name(), MYF(MY_WME));
2975 30767 ret_worker->master_log_change_notified = true;
2976
2977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30767 times.
30767 assert(!ptr_group->notified);
2978 #ifndef NDEBUG
2979 30767 ptr_group->notified = true;
2980 #endif
2981 }
2982
2983 /* Notify the worker about new FD */
2984
2/2
✓ Branch 0 taken 10464 times.
✓ Branch 1 taken 970002 times.
980466 if (!ret_worker->fd_change_notified) {
2985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10464 times.
10464 if (!ptr_group)
2986 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2987 /*
2988 Increment the usage counter on behalf of Worker.
2989 This avoids inadvertent FD deletion in a race case where Coordinator
2990 would install a next new FD before Worker has noticed the previous one.
2991 */
2992 10464 ++rli->get_rli_description_event()->atomic_usage_counter;
2993 10464 ptr_group->new_fd_event = rli->get_rli_description_event();
2994 10464 ret_worker->fd_change_notified = true;
2995 }
2996
2997
5/6
✓ Branch 0 taken 980466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 732007 times.
✓ Branch 3 taken 248459 times.
✓ Branch 4 taken 282116 times.
✓ Branch 5 taken 698350 times.
1712473 if (ends_group() ||
2998
4/4
✓ Branch 0 taken 33682 times.
✓ Branch 1 taken 698325 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 33624 times.
765689 (!rli->curr_group_seen_begin &&
2999 33682 (get_type_code() == binary_log::QUERY_EVENT ||
3000 /*
3001 When applying an old binary log without Gtid_log_event and
3002 Anonymous_gtid_log_event, the logic of multi-threaded slave
3003 still need to require that an event (for example, Query_log_event,
3004 User_var_log_event, Intvar_log_event, and Rand_log_event) that
3005 appeared outside of BEGIN...COMMIT was treated as a transaction
3006 of its own. This was just a technicality in the code and did not
3007 cause a problem, since the event and the following Query_log_event
3008 would both be assigned to dedicated worker 0.
3009 */
3010
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 25 times.
58 !rli->curr_group_seen_gtid))) {
3011 282116 rli->mts_group_status = Relay_log_info::MTS_END_GROUP;
3012
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 282088 times.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
282116 if (rli->curr_group_isolated) set_mts_isolate_group();
3013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282116 times.
282116 if (!ptr_group)
3014 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
3015
3016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282116 times.
282116 assert(ret_worker != nullptr);
3017
3018 // coordinator has ended buffering this group, update monitoring info
3019
3/4
✓ Branch 0 taken 282116 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 281989 times.
✓ Branch 3 taken 127 times.
282116 if (rli->is_processing_trx()) {
3020
7/12
✓ Branch 0 taken 281989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 281979 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 10 times.
281989 DBUG_EXECUTE_IF("rpl_ps_tables", {
3021 const char act[] =
3022 "now SIGNAL signal.rpl_ps_tables_process_before "
3023 "WAIT_FOR signal.rpl_ps_tables_process_finish";
3024 assert(opt_debug_sync_timeout > 0);
3025 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3026 };);
3027
1/2
✓ Branch 0 taken 281989 times.
✗ Branch 1 not taken.
281989 rli->finished_processing();
3028
7/12
✓ Branch 0 taken 281989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 281979 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 10 times.
281989 DBUG_EXECUTE_IF("rpl_ps_tables", {
3029 const char act[] =
3030 "now SIGNAL signal.rpl_ps_tables_process_after_finish "
3031 "WAIT_FOR signal.rpl_ps_tables_process_continue";
3032 assert(opt_debug_sync_timeout > 0);
3033 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3034 };);
3035 }
3036
3037 /*
3038 The following two blocks are executed if the worker has not been
3039 notified about new relay-log or a new checkpoints.
3040 Relay-log string is freed by Coordinator, Worker deallocates
3041 strings in the checkpoint block.
3042 However if the worker exits earlier reclaiming for both happens anyway at
3043 GAQ delete.
3044 */
3045
2/2
✓ Branch 0 taken 30530 times.
✓ Branch 1 taken 251586 times.
282116 if (!ret_worker->relay_log_change_notified) {
3046 /*
3047 Prior this event, C rotated the relay log to drop each
3048 Worker's notified flag. Now group terminating event initiates
3049 the new relay-log (where the current event is from) name
3050 delivery to Worker that will receive it in commit_positions().
3051 */
3052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30530 times.
30530 assert(ptr_group->group_relay_log_name == nullptr);
3053
3054 61060 ptr_group->group_relay_log_name = (char *)my_malloc(
3055
1/2
✓ Branch 0 taken 30530 times.
✗ Branch 1 not taken.
30530 key_memory_log_event, strlen(rli->get_group_relay_log_name()) + 1,
3056 MYF(MY_WME));
3057 30530 strcpy(ptr_group->group_relay_log_name, rli->get_event_relay_log_name());
3058
3059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30530 times.
30530 assert(ptr_group->group_relay_log_name != nullptr);
3060
3061 30530 ret_worker->relay_log_change_notified = true;
3062 }
3063
3064
2/2
✓ Branch 0 taken 118089 times.
✓ Branch 1 taken 164027 times.
282116 if (!ret_worker->checkpoint_notified) {
3065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 118089 times.
118089 if (!ptr_group)
3066 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
3067
1/2
✓ Branch 0 taken 118089 times.
✗ Branch 1 not taken.
118089 ptr_group->checkpoint_log_name = my_strdup(
3068 key_memory_log_event, rli->get_group_master_log_name(), MYF(MY_WME));
3069 118089 ptr_group->checkpoint_log_pos = rli->get_group_master_log_pos();
3070
1/2
✓ Branch 0 taken 118089 times.
✗ Branch 1 not taken.
118089 ptr_group->checkpoint_relay_log_name = my_strdup(
3071 key_memory_log_event, rli->get_group_relay_log_name(), MYF(MY_WME));
3072 118089 ptr_group->checkpoint_relay_log_pos = rli->get_group_relay_log_pos();
3073 118089 ptr_group->shifted = ret_worker->bitmap_shifted;
3074 118089 ret_worker->bitmap_shifted = 0;
3075 118089 ret_worker->checkpoint_notified = true;
3076 }
3077 282116 ptr_group->checkpoint_seqno = rli->rli_checkpoint_seqno;
3078 282116 ptr_group->ts = common_header->when.tv_sec +
3079 282116 (time_t)exec_time; // Seconds_behind_master related
3080 282116 rli->rli_checkpoint_seqno++;
3081 /*
3082 Coordinator should not use the main memroot however its not
3083 reset elsewhere either, so let's do it safe way.
3084 The main mem root is also reset by the SQL thread in at the end
3085 of applying which Coordinator does not do in this case.
3086 That concludes the memroot reset can't harm anything in SQL thread roles
3087 after Coordinator has finished its current scheduling.
3088 */
3089
1/2
✓ Branch 0 taken 282116 times.
✗ Branch 1 not taken.
282116 thd->mem_root->ClearForReuse();
3090
3091 #ifndef NDEBUG
3092 282116 w_rr++;
3093 #endif
3094 }
3095
3096 980466 return ret_worker;
3097 1511041 }
3098
3099 7 int Log_event::apply_gtid_event(Relay_log_info *rli) {
3100
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 DBUG_TRACE;
3101
3102 7 int error = 0;
3103
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if (rli->curr_group_da.size() < 1) return 1;
3104
3105
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 Log_event *ev = rli->curr_group_da[0].data;
3106
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
7 assert(ev->get_type_code() == binary_log::GTID_LOG_EVENT ||
3107 ev->get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT);
3108
3109
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 error = ev->do_apply_event(rli);
3110 /* Clean up */
3111
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 delete ev;
3112
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 rli->curr_group_da.clear();
3113 7 rli->curr_group_seen_gtid = false;
3114 /*
3115 Removes the job from the (G)lobal (A)ssigned (Q)ueue after
3116 applying it.
3117 */
3118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 assert(rli->gaq->get_length() > 0);
3119 7 Slave_job_group g = Slave_job_group();
3120
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 rli->gaq->de_tail(&g);
3121 /*
3122 The rli->mts_groups_assigned is increased when adding the slave job
3123 generated for the gtid into the (G)lobal (A)ssigned (Q)ueue. So we
3124 decrease it here.
3125 */
3126 7 rli->mts_groups_assigned--;
3127
3128 7 return error;
3129 7 }
3130
3131 /**
3132 Scheduling event to execute in parallel or execute it directly.
3133 In MTS case the event gets associated with either Coordinator or a
3134 Worker. A special case of the association is NULL when the Worker
3135 can't be decided yet. In the single threaded sequential mode the
3136 event maps to SQL thread rli.
3137
3138 @note in case of MTS failure Coordinator destroys all gathered
3139 deferred events.
3140
3141 @return 0 as success, otherwise a failure.
3142 */
3143 1782046 int Log_event::apply_event(Relay_log_info *rli) {
3144
1/2
✓ Branch 0 taken 1782152 times.
✗ Branch 1 not taken.
1782046 DBUG_TRACE;
3145
3/10
✓ Branch 0 taken 1782093 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1782131 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1782131 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1782152 DBUG_PRINT("info", ("event_type=%s", get_type_str()));
3146 1782131 bool parallel = false;
3147 1782131 enum enum_mts_event_exec_mode actual_exec_mode = EVENT_EXEC_PARALLEL;
3148 1782131 THD *rli_thd = rli->info_thd;
3149
3150 1782131 worker = rli;
3151
3152
2/2
✓ Branch 0 taken 1195 times.
✓ Branch 1 taken 1780895 times.
1782131 if (rli->is_mts_recovery()) {
3153
4/4
✓ Branch 0 taken 1094 times.
✓ Branch 1 taken 101 times.
✓ Branch 2 taken 1046 times.
✓ Branch 3 taken 48 times.
2289 bool skip = bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index) &&
3154 1094 (get_mts_execution_mode(rli->mts_group_status ==
3155 Relay_log_info::MTS_IN_GROUP) ==
3156 1195 EVENT_EXEC_PARALLEL);
3157
2/2
✓ Branch 0 taken 1046 times.
✓ Branch 1 taken 149 times.
1195 if (skip) {
3158 1046 return 0;
3159 } else {
3160
1/2
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
149 int error = do_apply_event(rli);
3161
3/4
✓ Branch 0 taken 149 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 56 times.
149 if (rli->is_processing_trx()) {
3162 // needed to identify DDL's; uses the same logic as in
3163 // get_slave_worker()
3164
6/8
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 76 times.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 76 times.
93 if (starts_group() && get_type_code() == binary_log::QUERY_EVENT) {
3165 17 rli->curr_group_seen_begin = true;
3166 }
3167
4/4
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 77 times.
185 if (error == 0 &&
3168
5/6
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 49 times.
92 (ends_group() || (get_type_code() == binary_log::QUERY_EVENT &&
3169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 !rli->curr_group_seen_begin))) {
3170
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 rli->finished_processing();
3171 16 rli->curr_group_seen_begin = false;
3172 }
3173 }
3174 149 return error;
3175 }
3176 }
3177
3178
7/8
✓ Branch 0 taken 1780914 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1595006 times.
✓ Branch 3 taken 185908 times.
✓ Branch 4 taken 83938 times.
✓ Branch 5 taken 1511067 times.
✓ Branch 6 taken 269849 times.
✓ Branch 7 taken 1511064 times.
3375900 if (!(parallel = rli->is_parallel_exec()) ||
3179 1595006 ((actual_exec_mode = get_mts_execution_mode(
3180 1595006 rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)) !=
3181 EVENT_EXEC_PARALLEL)) {
3182
2/2
✓ Branch 0 taken 83951 times.
✓ Branch 1 taken 185898 times.
269849 if (parallel) {
3183 /*
3184 There are two classes of events that Coordinator executes
3185 itself. One e.g the master Rotate requires all Workers to finish up
3186 their assignments. The other async class, e.g the slave Rotate,
3187 can't have this such synchronization because Worker might be waiting
3188 for terminal events to finish.
3189 */
3190
3191
2/2
✓ Branch 0 taken 41493 times.
✓ Branch 1 taken 42458 times.
83951 if (actual_exec_mode != EVENT_EXEC_ASYNC) {
3192 /*
3193 this event does not split the current group but is indeed
3194 a separator between two masters' binlogs therefore requiring
3195 Workers to sync.
3196 */
3197
6/12
✓ Branch 0 taken 41493 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 41486 times.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 41493 times.
41493 if (rli->curr_group_da.size() > 0 && is_mts_db_partitioned(rli) &&
3198 get_type_code() != binary_log::INCIDENT_EVENT) {
3199 char llbuff[22];
3200 /*
3201 Possible reason is a old version binlog sequential event
3202 wrappped with BEGIN/COMMIT or preceded by User|Int|Random- var.
3203 MTS has to stop to suggest restart in the permanent sequential
3204 mode.
3205 */
3206 llstr(rli->get_event_relay_log_pos(), llbuff);
3207 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
3208 rli->get_event_relay_log_name(), llbuff,
3209 "possible malformed group of events from an old master");
3210
3211 /* Coordinator cant continue, it marks MTS group status accordingly
3212 */
3213 rli->mts_group_status = Relay_log_info::MTS_KILLED_GROUP;
3214
3215 goto err;
3216 }
3217
3218 41493 if (get_type_code() == binary_log::INCIDENT_EVENT &&
3219
8/10
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 41485 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✓ Branch 9 taken 41486 times.
41500 rli->curr_group_da.size() > 0 &&
3220 7 rli->current_mts_submode->get_type() ==
3221 MTS_PARALLEL_TYPE_LOGICAL_CLOCK) {
3222 #ifndef NDEBUG
3223
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 assert(rli->curr_group_da.size() == 1);
3224
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 Log_event *ev = rli->curr_group_da[0].data;
3225
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
7 assert(ev->get_type_code() == binary_log::GTID_LOG_EVENT ||
3226 ev->get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT);
3227 #endif
3228 /*
3229 With MTS logical clock mode, when coordinator is applying an
3230 incident event, it must withdraw delegated_job increased by
3231 the incident's GTID before waiting for workers to finish.
3232 So that it can exit from mta_checkpoint_routine.
3233 */
3234 7 ((Mts_submode_logical_clock *)rli->current_mts_submode)
3235 7 ->withdraw_delegated_job();
3236 }
3237 /*
3238 Marking sure the event will be executed in sequential mode.
3239 */
3240
3/4
✓ Branch 0 taken 41295 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 41287 times.
41493 if (rli->current_mts_submode->wait_for_workers_to_finish(rli) == -1) {
3241 // handle synchronization error
3242
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 rli->report(WARNING_LEVEL, 0,
3243 "Slave worker thread has failed to apply an event. As a "
3244 "consequence, the coordinator thread is stopping "
3245 "execution.");
3246 8 return -1;
3247 }
3248 /*
3249 Given not in-group mark the event handler can invoke checkpoint
3250 update routine in the following course.
3251 */
3252
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 41287 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
41287 assert(rli->mts_group_status == Relay_log_info::MTS_NOT_IN_GROUP ||
3253 !is_mts_db_partitioned(rli));
3254
3255
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 41279 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 41280 times.
41295 if (get_type_code() == binary_log::INCIDENT_EVENT &&
3256
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
8 rli->curr_group_da.size() > 0) {
3257
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 assert(rli->curr_group_da.size() == 1);
3258 /*
3259 When MTS is enabled, the incident event must be applied by the
3260 coordinator. So the coordinator applies its GTID right before
3261 applying the incident event..
3262 */
3263
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 int error = apply_gtid_event(rli);
3264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (error) return -1;
3265 }
3266
3267 #ifndef NDEBUG
3268 /* all Workers are idle as done through wait_for_workers_to_finish */
3269
2/4
✓ Branch 0 taken 41287 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 41287 times.
41287 for (uint k = 0; k < rli->curr_group_da.size(); k++) {
3270 assert(!(rli->workers[k]->usage_partition));
3271 assert(!(rli->workers[k]->jobs.get_length()));
3272 }
3273 #endif
3274 } else {
3275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42458 times.
42458 assert(actual_exec_mode == EVENT_EXEC_ASYNC);
3276 }
3277 }
3278
3279
1/2
✓ Branch 0 taken 269604 times.
✗ Branch 1 not taken.
269643 int error = do_apply_event(rli);
3280
3/4
✓ Branch 0 taken 269694 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2598 times.
✓ Branch 3 taken 267096 times.
269604 if (rli->is_processing_trx()) {
3281 // needed to identify DDL's; uses the same logic as in get_slave_worker()
3282
6/8
✓ Branch 0 taken 2598 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 410 times.
✓ Branch 3 taken 2188 times.
✓ Branch 4 taken 410 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 410 times.
✓ Branch 7 taken 2188 times.
2598 if (starts_group() && get_type_code() == binary_log::QUERY_EVENT) {
3283 410 rli->curr_group_seen_begin = true;
3284 }
3285
4/4
✓ Branch 0 taken 2572 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 499 times.
✓ Branch 3 taken 2099 times.
5170 if (error == 0 &&
3286
5/6
✓ Branch 0 taken 2572 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2195 times.
✓ Branch 3 taken 377 times.
✓ Branch 4 taken 1094 times.
✓ Branch 5 taken 1101 times.
2572 (ends_group() || (get_type_code() == binary_log::QUERY_EVENT &&
3287
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 972 times.
1094 !rli->curr_group_seen_begin))) {
3288
2/12
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 499 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
499 DBUG_EXECUTE_IF("rpl_ps_tables", {
3289 const char act[] =
3290 "now SIGNAL signal.rpl_ps_tables_apply_before "
3291 "WAIT_FOR signal.rpl_ps_tables_apply_finish";
3292 assert(opt_debug_sync_timeout > 0);
3293 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3294 };);
3295
1/2
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
499 rli->finished_processing();
3296 499 rli->curr_group_seen_begin = false;
3297
2/12
✓ Branch 0 taken 499 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 499 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
499 DBUG_EXECUTE_IF("rpl_ps_tables", {
3298 const char act[] =
3299 "now SIGNAL signal.rpl_ps_tables_apply_after_finish "
3300 "WAIT_FOR signal.rpl_ps_tables_apply_continue";
3301 assert(opt_debug_sync_timeout > 0);
3302 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3303 };);
3304 }
3305 }
3306 269694 return error;
3307 }
3308
3309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1511064 times.
1511064 assert(actual_exec_mode == EVENT_EXEC_PARALLEL);
3310
10/28
✓ Branch 0 taken 946696 times.
✓ Branch 1 taken 564368 times.
✓ Branch 2 taken 946696 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 248366 times.
✓ Branch 5 taken 698330 times.
✓ Branch 6 taken 248365 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 248365 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 248366 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 248366 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
1511064 assert(!(rli->curr_group_seen_begin && ends_group()) ||
3311 /*
3312 This is an empty group being processed due to gtids.
3313 */
3314 (rli->curr_group_seen_begin && rli->curr_group_seen_gtid &&
3315 ends_group()) ||
3316 is_mts_db_partitioned(rli) || rli->last_assigned_worker ||
3317 /*
3318 Begin_load_query can be logged w/o db info and within
3319 Begin/Commit. That's a pattern forcing sequential
3320 applying of LOAD-DATA.
3321 */
3322 (rli->curr_group_da.back().data->get_type_code() ==
3323 binary_log::BEGIN_LOAD_QUERY_EVENT) ||
3324 /*
3325 Delete_file can also be logged w/o db info and within
3326 Begin/Commit. That's a pattern forcing sequential
3327 applying of LOAD-DATA.
3328 */
3329 (rli->curr_group_da.back().data->get_type_code() ==
3330 binary_log::DELETE_FILE_EVENT));
3331
3332 1511064 worker = nullptr;
3333 1511064 rli->mts_group_status = Relay_log_info::MTS_IN_GROUP;
3334
3335 1511043 worker =
3336
1/2
✓ Branch 0 taken 1511043 times.
✗ Branch 1 not taken.
1511064 (Relay_log_info *)(rli->last_assigned_worker = get_slave_worker(rli));
3337
3338 #ifndef NDEBUG
3339
2/2
✓ Branch 0 taken 530577 times.
✓ Branch 1 taken 980466 times.
1511043 if (rli->last_assigned_worker)
3340
3/8
✓ Branch 0 taken 980466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 980466 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 980466 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
980466 DBUG_PRINT("mts",
3341 ("Assigning job to worker %lu", rli->last_assigned_worker->id));
3342 #endif
3343
3344 530577 err:
3345
9/10
✓ Branch 0 taken 1511042 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1511035 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 530569 times.
✓ Branch 5 taken 980466 times.
✓ Branch 6 taken 87 times.
✓ Branch 7 taken 530483 times.
✓ Branch 8 taken 94 times.
✓ Branch 9 taken 1510949 times.
1511043 if (rli_thd->is_error() || (!worker && rli->abort_slave)) {
3346
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 assert(!worker);
3347
3348 /*
3349 Destroy all deferred buffered events but the current prior to exit.
3350 The current one will be deleted as an event never destined/assigned
3351 to any Worker in Coordinator's regular execution path.
3352 */
3353
3/4
✓ Branch 0 taken 186 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 92 times.
✓ Branch 3 taken 94 times.
186 for (uint k = 0; k < rli->curr_group_da.size(); k++) {
3354
1/2
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
92 Log_event *ev_buf = rli->curr_group_da[k].data;
3355
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
92 if (this != ev_buf) delete ev_buf;
3356 }
3357
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 rli->curr_group_da.clear();
3358 } else {
3359
4/6
✓ Branch 0 taken 530483 times.
✓ Branch 1 taken 980466 times.
✓ Branch 2 taken 530483 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 530483 times.
1510949 assert(worker || rli->curr_group_assigned_parts.size() == 0);
3360 }
3361
3362
5/6
✓ Branch 0 taken 1511043 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 530570 times.
✓ Branch 3 taken 980466 times.
✓ Branch 4 taken 87 times.
✓ Branch 5 taken 530483 times.
3022079 return (!(rli_thd->is_error() || (!worker && rli->abort_slave)) ||
3363
2/4
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 94 times.
94 DBUG_EVALUATE_IF("fault_injection_get_replica_worker", 1, 0))
3364
2/2
✓ Branch 0 taken 1511036 times.
✓ Branch 1 taken 7 times.
3022086 ? 0
3365 1511043 : -1;
3366 1781940 }
3367
3368 /**************************************************************************
3369 Query_log_event methods
3370 **************************************************************************/
3371
3372 /**
3373 This (which is used only for SHOW BINLOG EVENTS) could be updated to
3374 print SET @@session_var=. But this is not urgent, as SHOW BINLOG EVENTS is
3375 only an information, it does not produce suitable queries to replay (for
3376 example it does not print LOAD DATA INFILE).
3377 @todo
3378 show the catalog ??
3379 */
3380
3381 66190 int Query_log_event::pack_info(Protocol *protocol) {
3382 // TODO: show the catalog ??
3383 66190 String str_buf;
3384 // Add use `DB` to the string if required
3385
5/6
✓ Branch 0 taken 38996 times.
✓ Branch 1 taken 27194 times.
✓ Branch 2 taken 38996 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38988 times.
✓ Branch 5 taken 8 times.
66190 if (!(common_header->flags & LOG_EVENT_SUPPRESS_USE_F) && db && db_len) {
3386
1/2
✓ Branch 0 taken 38988 times.
✗ Branch 1 not taken.
38988 str_buf.append("use ");
3387
1/2
✓ Branch 0 taken 38988 times.
✗ Branch 1 not taken.
38988 append_identifier(this->thd, &str_buf, db, db_len);
3388
1/2
✓ Branch 0 taken 38988 times.
✗ Branch 1 not taken.
38988 str_buf.append("; ");
3389 }
3390 // Add the query to the string
3391
2/4
✓ Branch 0 taken 66190 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66190 times.
✗ Branch 3 not taken.
66190 if (query && q_len) {
3392
1/2
✓ Branch 0 taken 66190 times.
✗ Branch 1 not taken.
66190 str_buf.append(query);
3393
2/2
✓ Branch 0 taken 3740 times.
✓ Branch 1 taken 62450 times.
66190 if (ddl_xid != binary_log::INVALID_XID) {
3394 char xid_buf[64];
3395
1/2
✓ Branch 0 taken 3740 times.
✗ Branch 1 not taken.
3740 str_buf.append(" /* xid=");
3396
1/2
✓ Branch 0 taken 3740 times.
✗ Branch 1 not taken.
3740 longlong10_to_str(ddl_xid, xid_buf, 10);
3397
1/2
✓ Branch 0 taken 3740 times.
✗ Branch 1 not taken.
3740 str_buf.append(xid_buf);
3398
1/2
✓ Branch 0 taken 3740 times.
✗ Branch 1 not taken.
3740 str_buf.append(" */");
3399 }
3400 }
3401 // persist the buffer in protocol
3402
1/2
✓ Branch 0 taken 66190 times.
✗ Branch 1 not taken.
66190 protocol->store_string(str_buf.ptr(), str_buf.length(), &my_charset_bin);
3403 66190 return 0;
3404 66190 }
3405
3406 /**
3407 Utility function for the next method (Query_log_event::write()) .
3408 */
3409 3265450 static void write_str_with_code_and_len(uchar **dst, const char *src,
3410 size_t len, uint code) {
3411 /*
3412 only 1 byte to store the length of catalog, so it should not
3413 surpass 255
3414 */
3415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3265450 times.
3265450 assert(len <= 255);
3416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3265450 times.
3265450 assert(src);
3417 3265450 *((*dst)++) = code;
3418 3265450 *((*dst)++) = (uchar)len;
3419 3265450 memmove(*dst, src, len);
3420 3265450 (*dst) += len;
3421 3265450 }
3422
3423 /**
3424 Query_log_event::write().
3425
3426 @note
3427 In this event we have to modify the header to have the correct
3428 EVENT_LEN_OFFSET as we don't yet know how many status variables we
3429 will print!
3430 */
3431
3432 3402887 bool Query_log_event::write(Basic_ostream *ostream) {
3433 uchar buf[Binary_log_event::QUERY_HEADER_LEN + MAX_SIZE_LOG_EVENT_STATUS];
3434 uchar *start, *start_of_status;
3435 size_t event_length;
3436
3437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3402887 times.
3402887 if (!query) return true; // Something wrong with event
3438
3439 /*
3440 We want to store the thread id:
3441 (- as an information for the user when he reads the binlog)
3442 - if the query uses temporary table: for the slave SQL thread to know to
3443 which master connection the temp table belongs.
3444 Now imagine we (write()) are called by the slave SQL thread (we are
3445 logging a query executed by this thread; the slave runs with
3446 --log-replica-updates). Then this query will be logged with
3447 thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of
3448 the same name were created simultaneously on the master (in the masters
3449 binlog you have
3450 CREATE TEMPORARY TABLE t; (thread 1)
3451 CREATE TEMPORARY TABLE t; (thread 2)
3452 ...)
3453 then in the slave's binlog there will be
3454 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3455 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3456 which is bad (same thread id!).
3457
3458 To avoid this, we log the thread's thread id EXCEPT for the SQL
3459 slave thread for which we log the original (master's) thread id.
3460 Now this moves the bug: what happens if the thread id on the
3461 master was 10 and when the slave replicates the query, a
3462 connection number 10 is opened by a normal client on the slave,
3463 and updates a temp table of the same name? We get a problem
3464 again. To avoid this, in the handling of temp tables (sql_base.cc)
3465 we use thread_id AND server_id. TODO when this is merged into
3466 4.1: in 4.1, slave_proxy_id has been renamed to pseudo_thread_id
3467 and is a session variable: that's to make mysqlbinlog work with
3468 temp tables. We probably need to introduce
3469
3470 SET PSEUDO_SERVER_ID
3471 for mysqlbinlog in 4.1. mysqlbinlog would print:
3472 SET PSEUDO_SERVER_ID=
3473 SET PSEUDO_THREAD_ID=
3474 for each query using temp tables.
3475 */
3476 3402887 int4store(buf + Q_THREAD_ID_OFFSET, slave_proxy_id);
3477 3402722 int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
3478 3402760 buf[Q_DB_LEN_OFFSET] = (char)db_len;
3479 3402760 int2store(buf + Q_ERR_CODE_OFFSET, error_code);
3480
3481 /*
3482 You MUST always write status vars in increasing order of code. This
3483 guarantees that a slightly older slave will be able to parse those he
3484 knows.
3485 */
3486 3402859 start_of_status = start = buf + Binary_log_event::QUERY_HEADER_LEN;
3487
1/2
✓ Branch 0 taken 3402977 times.
✗ Branch 1 not taken.
3402859 if (flags2_inited) {
3488 3402977 *start++ = Q_FLAGS2_CODE;
3489 3402977 int4store(start, flags2);
3490 3403042 start += 4;
3491 }
3492
1/2
✓ Branch 0 taken 3403097 times.
✗ Branch 1 not taken.
3402924 if (sql_mode_inited) {
3493 3403097 *start++ = Q_SQL_MODE_CODE;
3494 3403097 int8store(start, sql_mode);
3495 3403137 start += 8;
3496 }
3497
2/2
✓ Branch 0 taken 3209511 times.
✓ Branch 1 taken 193453 times.
3402964 if (catalog_len) // i.e. this var is inited (false for 4.0 events)
3498 {
3499 3209511 write_str_with_code_and_len(&start, catalog, catalog_len,
3500 Q_CATALOG_NZ_CODE);
3501 /*
3502 In 5.0.x where x<4 masters we used to store the end zero here. This was
3503 a waste of one byte so we don't do it in x>=4 masters. We change code to
3504 Q_CATALOG_NZ_CODE, because re-using the old code would make x<4 slaves
3505 of this x>=4 master segfault (expecting a zero when there is
3506 none). Remaining compatibility problems are: the older slave will not
3507 find the catalog; but it is will not crash, and it's not an issue
3508 that it does not find the catalog as catalogs were not used in these
3509 older MySQL versions (we store it in binlog and read it from relay log
3510 but do nothing useful with it). What is an issue is that the older slave
3511 will stop processing the Q_* blocks (and jumps to the db/query) as soon
3512 as it sees unknown Q_CATALOG_NZ_CODE; so it will not be able to read
3513 Q_AUTO_INCREMENT*, Q_CHARSET and so replication will fail silently in
3514 various ways. Documented that you should not mix alpha/beta versions if
3515 they are not exactly the same version, with example of 5.0.3->5.0.2 and
3516 5.0.4->5.0.3. If replication is from older to new, the new will
3517 recognize Q_CATALOG_CODE and have no problem.
3518 */
3519 }
3520
4/4
✓ Branch 0 taken 3322433 times.
✓ Branch 1 taken 80218 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 3322401 times.
3402651 if (auto_increment_increment != 1 || auto_increment_offset != 1) {
3521 80250 *start++ = Q_AUTO_INCREMENT;
3522 80250 int2store(start, static_cast<uint16>(auto_increment_increment));
3523 80411 int2store(start + 2, static_cast<uint16>(auto_increment_offset));
3524 80411 start += 4;
3525 }
3526
2/2
✓ Branch 0 taken 3402792 times.
✓ Branch 1 taken 20 times.
3402812 if (charset_inited) {
3527 3402792 *start++ = Q_CHARSET_CODE;
3528 3402792 memcpy(start, charset, 6);
3529 3402792 start += 6;
3530 }
3531
2/2
✓ Branch 0 taken 56384 times.
✓ Branch 1 taken 3346428 times.
3402812 if (time_zone_len) {
3532 /* In the TZ sys table, column Name is of length 64 so this should be ok */
3533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56384 times.
56384 assert(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
3534 56384 write_str_with_code_and_len(&start, time_zone_str, time_zone_len,
3535 Q_TIME_ZONE_CODE);
3536 }
3537
2/2
✓ Branch 0 taken 2984 times.
✓ Branch 1 taken 3399595 times.
3402579 if (lc_time_names_number) {
3538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2984 times.
2984 assert(lc_time_names_number <= 0xFF);
3539 2984 *start++ = Q_LC_TIME_NAMES_CODE;
3540 2984 int2store(start, lc_time_names_number);
3541 2984 start += 2;
3542 }
3543
2/2
✓ Branch 0 taken 7590 times.
✓ Branch 1 taken 3394989 times.
3402579 if (charset_database_number) {
3544 7590 *start++ = Q_CHARSET_DATABASE_CODE;
3545 7590 int2store(start, charset_database_number);
3546 7590 start += 2;
3547 }
3548
2/2
✓ Branch 0 taken 77091 times.
✓ Branch 1 taken 3325488 times.
3402579 if (table_map_for_update) {
3549 77091 *start++ = Q_TABLE_MAP_FOR_UPDATE_CODE;
3550 77091 int8store(start, table_map_for_update);
3551 77091 start += 8;
3552 }
3553
3554
5/6
✓ Branch 0 taken 3402585 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38301 times.
✓ Branch 3 taken 3364324 times.
✓ Branch 4 taken 38301 times.
✓ Branch 5 taken 3364318 times.
3402579 if (thd && thd->need_binlog_invoker()) {
3555 38301 LEX_CSTRING invoker_user{nullptr, 0};
3556 38301 LEX_CSTRING invoker_host{nullptr, 0};
3557 38301 memset(&invoker_user, 0, sizeof(invoker_user));
3558 38301 memset(&invoker_host, 0, sizeof(invoker_host));
3559
3560
6/6
✓ Branch 0 taken 2878 times.
✓ Branch 1 taken 35423 times.
✓ Branch 2 taken 2869 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 2869 times.
✓ Branch 5 taken 35432 times.
38301 if (thd->slave_thread && thd->has_invoker()) {
3561 /* user will be null, if master is older than this patch */
3562 2869 invoker_user = thd->get_invoker_user();
3563 2869 invoker_host = thd->get_invoker_host();
3564 } else {
3565 35432 Security_context *ctx = thd->security_context();
3566
1/2
✓ Branch 0 taken 35432 times.
✗ Branch 1 not taken.
35432 LEX_CSTRING priv_user = ctx->priv_user();
3567
1/2
✓ Branch 0 taken 35432 times.
✗ Branch 1 not taken.
35432 LEX_CSTRING priv_host = ctx->priv_host();
3568
3569 35432 invoker_user.length = priv_user.length;
3570 35432 invoker_user.str = priv_user.str;
3571
2/2
✓ Branch 0 taken 35426 times.
✓ Branch 1 taken 6 times.
35432 if (priv_host.str[0] != '\0') {
3572 35426 invoker_host.str = priv_host.str;
3573 35426 invoker_host.length = priv_host.length;
3574 }
3575 }
3576
3577 38301 *start++ = Q_INVOKER;
3578
3579
3/4
✓ Branch 0 taken 38301 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 38300 times.
38301 DBUG_EXECUTE_IF("wl12571_long_invoker_host", {
3580 invoker_host.str =
3581 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3582 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3583 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3584 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
3585 invoker_host.length = strlen(invoker_host.str);
3586 });
3587
3588 /*
3589 Store user length and user. The max length of use is 16, so 1 byte is
3590 enough to store the user's length.
3591 */
3592 38301 *start++ = (uchar)invoker_user.length;
3593 38301 memcpy(start, invoker_user.str, invoker_user.length);
3594 38301 start += invoker_user.length;
3595
3596 /*
3597 Store host length and host. The max length of host is 255, so 1 byte
3598 is enough to store the host's length.
3599 */
3600 38301 *start++ = (uchar)invoker_host.length;
3601
2/2
✓ Branch 0 taken 38294 times.
✓ Branch 1 taken 7 times.
38301 if (invoker_host.length > 0)
3602 38294 memcpy(start, invoker_host.str, invoker_host.length);
3603 38301 start += invoker_host.length;
3604 }
3605
3606
6/6
✓ Branch 0 taken 3402571 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 955257 times.
✓ Branch 3 taken 2447590 times.
✓ Branch 4 taken 955295 times.
✓ Branch 5 taken 2447600 times.
3402619 if (thd && thd->get_binlog_accessed_db_names() != nullptr) {
3607 uchar dbs;
3608 955295 *start++ = Q_UPDATED_DB_NAMES;
3609
3610 static_assert(MAX_DBS_IN_EVENT_MTS <= OVER_MAX_DBS_IN_EVENT_MTS, "");
3611
3612 /*
3613 In case of the number of db:s exceeds MAX_DBS_IN_EVENT_MTS
3614 no db:s is written and event will require the sequential applying on
3615 slave.
3616 */
3617 88 dbs =
3618
2/2
✓ Branch 0 taken 955254 times.
✓ Branch 1 taken 88 times.
955295 (thd->get_binlog_accessed_db_names()->elements <= MAX_DBS_IN_EVENT_MTS)
3619 955254 ? thd->get_binlog_accessed_db_names()->elements
3620 : OVER_MAX_DBS_IN_EVENT_MTS;
3621
3622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 955421 times.
955421 assert(dbs != 0);
3623
3624
2/2
✓ Branch 0 taken 955324 times.
✓ Branch 1 taken 97 times.
955421 if (dbs <= MAX_DBS_IN_EVENT_MTS) {
3625
1/2
✓ Branch 0 taken 955088 times.
✗ Branch 1 not taken.
955324 List_iterator_fast<char> it(*thd->get_binlog_accessed_db_names());
3626 955088 char *db_name = it++;
3627 /*
3628 the single "" db in the accessed db list corresponds to the same as
3629 exceeds MAX_DBS_IN_EVENT_MTS case, so dbs is set to the over-max.
3630 */
3631
4/4
✓ Branch 0 taken 948815 times.
✓ Branch 1 taken 6514 times.
✓ Branch 2 taken 1108 times.
✓ Branch 3 taken 947707 times.
955329 if (dbs == 1 && !strcmp(db_name, "")) dbs = OVER_MAX_DBS_IN_EVENT_MTS;
3632 955329 *start++ = dbs;
3633
2/2
✓ Branch 0 taken 954280 times.
✓ Branch 1 taken 1049 times.
955329 if (dbs != OVER_MAX_DBS_IN_EVENT_MTS) do {
3634 972226 strcpy((char *)start, db_name);
3635 972226 start += strlen(db_name) + 1;
3636
2/2
✓ Branch 0 taken 17946 times.
✓ Branch 1 taken 954264 times.
972226 } while ((db_name = it++));
3637 } else {
3638 97 *start++ = dbs;
3639 }
3640 }
3641
3642
4/4
✓ Branch 0 taken 3402909 times.
✓ Branch 1 taken 101 times.
✓ Branch 2 taken 15041 times.
✓ Branch 3 taken 3387868 times.
3403010 if (thd && thd->query_start_usec_used) {
3643 15041 *start++ = Q_MICROSECONDS;
3644
1/2
✓ Branch 0 taken 15041 times.
✗ Branch 1 not taken.
15041 get_time();
3645 15041 int3store(start, common_header->when.tv_usec);
3646 15041 start += 3;
3647 }
3648
3649
4/4
✓ Branch 0 taken 3402961 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 20160 times.
✓ Branch 3 taken 3382801 times.
3403010 if (thd && thd->binlog_need_explicit_defaults_ts == true) {
3650 20160 *start++ = Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP;
3651 20160 *start++ = thd->variables.explicit_defaults_for_timestamp;
3652 }
3653
3654
2/2
✓ Branch 0 taken 317991 times.
✓ Branch 1 taken 3085019 times.
3403010 if (ddl_xid != binary_log::INVALID_XID) {
3655 317991 *start++ = Q_DDL_LOGGED_WITH_XID;
3656 317991 int8store(start, ddl_xid);
3657 317991 start += 8;
3658 }
3659
3660
2/2
✓ Branch 0 taken 3402819 times.
✓ Branch 1 taken 191 times.
3403010 if (default_collation_for_utf8mb4_number) {
3661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3402819 times.
3402819 assert(default_collation_for_utf8mb4_number <= 0xFF);
3662 3402819 *start++ = Q_DEFAULT_COLLATION_FOR_UTF8MB4;
3663 3402819 int2store(start, default_collation_for_utf8mb4_number);
3664 3402862 start += 2;
3665 }
3666
3667
4/4
✓ Branch 0 taken 3402931 times.
✓ Branch 1 taken 122 times.
✓ Branch 2 taken 169908 times.
✓ Branch 3 taken 3233023 times.
3403053 if (thd && need_sql_require_primary_key) {
3668 169908 *start++ = Q_SQL_REQUIRE_PRIMARY_KEY;
3669 169908 *start++ = thd->variables.sql_require_primary_key;
3670 }
3671
3672
4/4
✓ Branch 0 taken 3402966 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 4445 times.
✓ Branch 3 taken 3398521 times.
3403053 if (thd && needs_default_table_encryption) {
3673 4445 *start++ = Q_DEFAULT_TABLE_ENCRYPTION;
3674 4445 *start++ = thd->variables.default_table_encryption;
3675 }
3676
3677
4/4
✓ Branch 0 taken 3402806 times.
✓ Branch 1 taken 247 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 3402758 times.
3403053 if (thd && thd->variables.binlog_ddl_skip_rewrite) {
3678 48 *start++ = Q_DDL_SKIP_REWRITE;
3679 48 *start++ = thd->variables.binlog_ddl_skip_rewrite;
3680 }
3681
3682 /*
3683 NOTE: When adding new status vars, please don't forget to update
3684 the MAX_SIZE_LOG_EVENT_STATUS in log_event.h
3685
3686 Here there could be code like
3687 if (command-line-option-which-says-"log_this_variable" && inited)
3688 {
3689 *start++= Q_THIS_VARIABLE_CODE;
3690 int4store(start, this_variable);
3691 start+= 4;
3692 }
3693 */
3694
3695 /* Store length of status variables */
3696 3403053 status_vars_len = (uint)(start - start_of_status);
3697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3403053 times.
3403053 assert(status_vars_len <= MAX_SIZE_LOG_EVENT_STATUS);
3698 3403053 int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len);
3699
3700 /*
3701 Calculate length of whole event
3702 The "1" below is the \0 in the db's length
3703 */
3704
1/2
✓ Branch 0 taken 3402618 times.
✗ Branch 1 not taken.
3402973 event_length = (uint)(start - buf) + get_post_header_size_for_derived() +
3705 3402618 db_len + 1 + q_len;
3706
3707
1/2
✓ Branch 0 taken 3403184 times.
✗ Branch 1 not taken.
3402618 return (write_header(ostream, event_length) ||
3708
2/4
✓ Branch 0 taken 3403185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3403191 times.
✗ Branch 3 not taken.
3403195 wrapper_my_b_safe_write(ostream, (uchar *)buf,
3709 3402919 Binary_log_event::QUERY_HEADER_LEN) ||
3710
2/4
✓ Branch 0 taken 3402919 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3402971 times.
✗ Branch 3 not taken.
3403191 write_post_header_for_derived(ostream) ||
3711
1/2
✓ Branch 0 taken 3403117 times.
✗ Branch 1 not taken.
3403099 wrapper_my_b_safe_write(ostream, start_of_status,
3712
1/2
✓ Branch 0 taken 3403099 times.
✗ Branch 1 not taken.
3402971 (uint)(start - start_of_status)) ||
3713
3/4
✓ Branch 0 taken 3403229 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3403225 times.
✓ Branch 3 taken 4 times.
3402996 wrapper_my_b_safe_write(ostream,
3714 3349278 db ? pointer_cast<const uchar *>(db)
3715 53839 : pointer_cast<const uchar *>(""),
3716
2/2
✓ Branch 0 taken 3349278 times.
✓ Branch 1 taken 53839 times.
3403117 db_len + 1) ||
3717
3/4
✓ Branch 0 taken 3403282 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3403144 times.
✓ Branch 3 taken 138 times.
3403225 wrapper_my_b_safe_write(ostream, pointer_cast<const uchar *>(query),
3718 q_len) ||
3719
1/2
✓ Branch 0 taken 3403209 times.
✗ Branch 1 not taken.
3403144 write_footer(ostream))
3720
2/4
✓ Branch 0 taken 3403195 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3403211 times.
6806459 ? true
3721 3403264 : false;
3722 }
3723
3724 /**
3725 The simplest constructor that could possibly work. This is used for
3726 creating static objects that have a special meaning and are invisible
3727 to the log.
3728 */
3729 Query_log_event::Query_log_event()
3730 : binary_log::Query_event(),
3731 Log_event(header(), footer()),
3732 data_buf(nullptr) {}
3733
3734 /**
3735 Returns true when the lex context determines an atomic DDL.
3736 The result is optimistic as there can be more properties to check out.
3737
3738 CREATE TABLE ... START TRANSACTION is not treated as atomic here, because
3739 the table is not really committed at the end of CREATE TABLE processing.
3740 It gets committed by a explicit call to COMMIT after INSERTing rows into
3741 the table.
3742
3743 @param lex pointer to LEX object of being executed statement
3744 */
3745 582905 inline bool is_sql_command_atomic_ddl(const LEX *lex) {
3746 751857 return ((sql_command_flags[lex->sql_command] & CF_POTENTIAL_ATOMIC_DDL) &&
3747
1/2
✓ Branch 0 taken 168952 times.
✗ Branch 1 not taken.
168952 lex->sql_command != SQLCOM_OPTIMIZE &&
3748
1/2
✓ Branch 0 taken 168952 times.
✗ Branch 1 not taken.
168952 lex->sql_command != SQLCOM_REPAIR &&
3749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168952 times.
168952 lex->sql_command != SQLCOM_ANALYZE) ||
3750
2/2
✓ Branch 0 taken 128803 times.
✓ Branch 1 taken 285150 times.
413953 (lex->sql_command == SQLCOM_CREATE_TABLE &&
3751
2/2
✓ Branch 0 taken 121120 times.
✓ Branch 1 taken 7683 times.
128803 !(lex->create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
3752
4/4
✓ Branch 0 taken 168952 times.
✓ Branch 1 taken 413953 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 121057 times.
1165873 !lex->create_info->m_transactional_ddl) ||
3753
4/4
✓ Branch 0 taken 82515 times.
✓ Branch 1 taken 210381 times.
✓ Branch 2 taken 81718 times.
✓ Branch 3 taken 797 times.
875801 (lex->sql_command == SQLCOM_DROP_TABLE && !lex->drop_temporary);
3754 }
3755
3756 /**
3757 Returns whether or not the statement held by the `LEX` object parameter
3758 requires `Q_SQL_REQUIRE_PRIMARY_KEY` to be logged together with the statement.
3759 */
3760 877375 static bool is_sql_require_primary_key_needed(const LEX *lex) {
3761 877375 enum enum_sql_command cmd = lex->sql_command;
3762
2/2
✓ Branch 0 taken 183410 times.
✓ Branch 1 taken 693965 times.
877375 switch (cmd) {
3763 183410 case SQLCOM_CREATE_TABLE:
3764 case SQLCOM_ALTER_TABLE:
3765 183410 return true;
3766 693965 default:
3767 693965 break;
3768 }
3769 693965 return false;
3770 }
3771
3772 /**
3773 Returns whether or not the statement held by the `LEX` object parameter
3774 requires `Q_DEFAULT_TABLE_ENCRYPTION` to be logged together with the
3775 statement.
3776 */
3777 877390 static bool is_default_table_encryption_needed(const LEX *lex) {
3778 877390 enum enum_sql_command cmd = lex->sql_command;
3779
3/3
✓ Branch 0 taken 5025 times.
✓ Branch 1 taken 7138 times.
✓ Branch 2 taken 865227 times.
877390 switch (cmd) {
3780 5025 case SQLCOM_CREATE_DB:
3781 // If it is CREATE DATABASE without an ENCRYPTION clause
3782 5025 return !(lex->create_info->used_fields &
3783 5025 HA_CREATE_USED_DEFAULT_ENCRYPTION);
3784 7138 case SQLCOM_ALTER_TABLESPACE: {
3785 /*
3786 If it is CREATE TABLESPACE without an ENCRYPTION clause. Note
3787 that CREATE TABLESPACE uses SQLCOM_ALTER_TABLESPACE, so to
3788 know if it is really a CREATE TABLESPACE we check that the
3789 dynamic_cast to Sql_cmd_create_tablespace works.
3790 */
3791 7138 const Sql_cmd_tablespace *sct =
3792
1/2
✓ Branch 0 taken 7138 times.
✗ Branch 1 not taken.
7138 dynamic_cast<const Sql_cmd_create_tablespace *>(lex->m_sql_cmd);
3793
2/2
✓ Branch 0 taken 876 times.
✓ Branch 1 taken 6262 times.
8014 return ((sct != nullptr) &&
3794
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 509 times.
8014 (sct->get_options().encryption.str == nullptr));
3795 }
3796 865227 default:
3797 865227 break;
3798 }
3799 865227 return false;
3800 }
3801
3802 719856 bool is_atomic_ddl(THD *thd, bool using_trans_arg) {
3803 719856 LEX *lex = thd->lex;
3804
3805 #ifndef NDEBUG
3806 719856 enum enum_sql_command cmd = lex->sql_command;
3807
3/3
✓ Branch 0 taken 69538 times.
✓ Branch 1 taken 31614 times.
✓ Branch 2 taken 618704 times.
719856 switch (cmd) {
3808 69538 case SQLCOM_CREATE_USER:
3809 case SQLCOM_RENAME_USER:
3810 case SQLCOM_DROP_USER:
3811 case SQLCOM_ALTER_USER:
3812 case SQLCOM_ALTER_USER_DEFAULT_ROLE:
3813 case SQLCOM_GRANT:
3814 case SQLCOM_GRANT_ROLE:
3815 case SQLCOM_REVOKE:
3816 case SQLCOM_REVOKE_ALL:
3817 case SQLCOM_REVOKE_ROLE:
3818 case SQLCOM_DROP_ROLE:
3819 case SQLCOM_CREATE_ROLE:
3820 case SQLCOM_SET_PASSWORD:
3821 case SQLCOM_DROP_TRIGGER:
3822 case SQLCOM_ALTER_FUNCTION:
3823 case SQLCOM_DROP_FUNCTION:
3824 case SQLCOM_DROP_PROCEDURE:
3825 case SQLCOM_ALTER_PROCEDURE:
3826 case SQLCOM_ALTER_EVENT:
3827 case SQLCOM_DROP_EVENT:
3828 case SQLCOM_CREATE_VIEW:
3829 case SQLCOM_DROP_VIEW:
3830
3831 #ifdef WITH_WSREP
3832 /*
3833 MySQL-8.0 enabled atomic DDL but to PXC still needs time to adapt to
3834 real atomic DDL flow so for now DDL still use TOI sequence.
3835 When the Query_log_event is generated for TOI replication, skip
3836 the said test/assert that check if the transaction is enabled for
3837 atomic ddl supporting statement. Use of wsrep_skip_wsrep_hton is really
3838 a hack or short-cut to avoid introducing another variable for this
3839 */
3840
7/8
✓ Branch 0 taken 5008 times.
✓ Branch 1 taken 64530 times.
✓ Branch 2 taken 4775 times.
✓ Branch 3 taken 233 times.
✓ Branch 4 taken 360 times.
✓ Branch 5 taken 4415 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 360 times.
69538 assert(using_trans_arg || thd->slave_thread || lex->drop_if_exists ||
3841 thd->wsrep_skip_wsrep_hton);
3842 #else
3843 assert(using_trans_arg || thd->slave_thread || lex->drop_if_exists);
3844 #endif /* WITH_WSREP */
3845
3846 69538 break;
3847
3848 31614 case SQLCOM_CREATE_EVENT:
3849 case SQLCOM_CREATE_PROCEDURE:
3850 case SQLCOM_CREATE_SPFUNCTION:
3851 case SQLCOM_CREATE_FUNCTION:
3852 case SQLCOM_CREATE_TRIGGER:
3853 /*
3854 trx cache is *not* used if object already exists and IF NOT EXISTS
3855 clause is used in the statement or if call is from the slave applier.
3856 */
3857 #ifdef WITH_WSREP
3858
6/8
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 31493 times.
✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 99 times.
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 99 times.
31614 assert(using_trans_arg || thd->slave_thread ||
3859 (lex->create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) ||
3860 thd->wsrep_skip_wsrep_hton);
3861 #else
3862 assert(using_trans_arg || thd->slave_thread ||
3863 (lex->create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS));
3864 #endif /* WITH_WSREP */
3865 31614 break;
3866
3867 618704 default:
3868 618704 break;
3869 }
3870 #endif
3871
3872
4/4
✓ Branch 0 taken 582932 times.
✓ Branch 1 taken 136924 times.
✓ Branch 2 taken 371727 times.
✓ Branch 3 taken 211215 times.
719856 return using_trans_arg && is_sql_command_atomic_ddl(lex);
3873 }
3874
3875 /**
3876 Creates a Query Log Event.
3877
3878 @param thd_arg Thread handle
3879 @param query_arg Array of char representing the query
3880 @param query_length Size of the 'query_arg' array
3881 @param using_trans Indicates that there are transactional changes.
3882 @param immediate After being written to the binary log, the event
3883 must be flushed immediately. This indirectly implies
3884 the stmt-cache.
3885 @param suppress_use Suppress the generation of 'USE' statements
3886 @param errcode The error code of the query
3887 @param ignore_cmd_internals Ignore user's statement, i.e. lex
3888 information, while deciding which cache must be used.
3889 */
3890 7062120 Query_log_event::Query_log_event(THD *thd_arg, const char *query_arg,
3891 size_t query_length, bool using_trans,
3892 bool immediate, bool suppress_use, int errcode,
3893 7054088 bool ignore_cmd_internals)
3894
3895 : binary_log::Query_event(
3896 7054808 query_arg, thd_arg->catalog().str, thd_arg->db().str, query_length,
3897 7054088 thd_arg->thread_id(), thd_arg->variables.sql_mode,
3898 thd_arg->variables.auto_increment_increment,
3899 thd_arg->variables.auto_increment_offset,
3900 7054088 thd_arg->variables.lc_time_names->number,
3901 7054088 (ulonglong)thd_arg->table_map_for_update, errcode),
3902 Log_event(
3903 thd_arg,
3904
4/4
✓ Branch 0 taken 200768 times.
✓ Branch 1 taken 3331257 times.
✓ Branch 2 taken 2674822 times.
✓ Branch 3 taken 857203 times.
7064050 (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0) |
3905 (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
3906 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
3907 : Log_event::EVENT_STMT_CACHE,
3908 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
3909
5/6
✓ Branch 0 taken 3495 times.
✓ Branch 1 taken 521 times.
✓ Branch 2 taken 2513828 times.
✓ Branch 3 taken 1014181 times.
✓ Branch 4 taken 3527584 times.
✗ Branch 5 not taken.
21180912 data_buf(nullptr) {
3910 #ifdef WITH_WSREP
3911 /*
3912 If Query_log_event will contain non trans keyword (not BEGIN, COMMIT,
3913 SAVEPOINT or ROLLBACK) we disable PA for this transaction.
3914 */
3915 /* PA_safe = true indicate that write-set can be applied in parallel. */
3916
2/2
✓ Branch 0 taken 868400 times.
✓ Branch 1 taken 2663230 times.
7063200 if (!is_trans_keyword()) thd->wsrep_PA_safe = false;
3917 #endif /* WITH_WSREP */
3918
3919 /* save the original thread id; we already know the server id */
3920 7063260 slave_proxy_id = thd_arg->variables.pseudo_thread_id;
3921 7063260 common_header->set_is_valid(query != nullptr);
3922
3923 /*
3924 exec_time calculation has changed to use the same method that is used
3925 to fill out "thd_arg->start_time"
3926 */
3927
3928 struct timeval end_time;
3929 7063580 ulonglong micro_end_time = my_micro_time();
3930 7063816 my_micro_time_to_timeval(micro_end_time, &end_time);
3931
3932 7063214 exec_time = end_time.tv_sec - thd_arg->query_start_in_secs();
3933
3934 /**
3935 @todo this means that if we have no catalog, then it is replicated
3936 as an existing catalog of length zero. is that safe? /sven
3937 */
3938
2/2
✓ Branch 0 taken 3337970 times.
✓ Branch 1 taken 193472 times.
7062884 catalog_len = (catalog) ? strlen(catalog) : 0;
3939 /* status_vars_len is set just before writing the event */
3940
2/2
✓ Branch 0 taken 3473055 times.
✓ Branch 1 taken 58387 times.
7062884 db_len = (db) ? strlen(db) : 0;
3941
2/2
✓ Branch 0 taken 7654 times.
✓ Branch 1 taken 3523788 times.
7062884 if (thd_arg->variables.collation_database != thd_arg->db_charset)
3942 15308 charset_database_number = thd_arg->variables.collation_database->number;
3943
3944 7062884 default_collation_for_utf8mb4_number =
3945 7062884 thd_arg->variables.default_collation_for_utf8mb4->number;
3946
3947 /*
3948 We only replicate over the bits of flags2 that we need: the rest
3949 are masked out by "& OPTIONS_WRITTEN_TO_BINLOG".
3950
3951 We also force AUTOCOMMIT=1. Rationale (cf. BUG#29288): After
3952 fixing BUG#26395, we always write BEGIN and COMMIT around all
3953 transactions (even single statements in autocommit mode). This is
3954 so that replication from non-transactional to transactional table
3955 and error recovery from XA to non-XA table should work as
3956 expected. The BEGIN/COMMIT are added in log.cc. However, there is
3957 one exception: MyISAM bypasses log.cc and writes directly to the
3958 binlog. So if autocommit is off, master has MyISAM, and slave has
3959 a transactional engine, then the slave will just see one long
3960 never-ending transaction. The only way to bypass explicit
3961 BEGIN/COMMIT in the binlog is by using a non-transactional table.
3962 So setting AUTOCOMMIT=1 will make this work as expected.
3963
3964 Note: explicitly replicate AUTOCOMMIT=1 from master. We do not
3965 assume AUTOCOMMIT=1 on slave; the slave still reads the state of
3966 the autocommit flag as written by the master to the binlog. This
3967 behavior may change after WL#4162 has been implemented.
3968 */
3969 7062884 flags2 = (uint32)(thd_arg->variables.option_bits &
3970 (OPTIONS_WRITTEN_TO_BIN_LOG & ~OPTION_NOT_AUTOCOMMIT));
3971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3531442 times.
7062884 assert(thd_arg->variables.character_set_client->number < 256 * 256);
3972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3531442 times.
7062884 assert(thd_arg->variables.collation_connection->number < 256 * 256);
3973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3531442 times.
7062884 assert(thd_arg->variables.collation_server->number < 256 * 256);
3974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3531442 times.
7062884 assert(thd_arg->variables.character_set_client->mbminlen == 1);
3975 7062884 int2store(charset, thd_arg->variables.character_set_client->number);
3976 7063362 int2store(charset + 2, thd_arg->variables.collation_connection->number);
3977 7063870 int2store(charset + 4, thd_arg->variables.collation_server->number);
3978
2/2
✓ Branch 0 taken 62395 times.
✓ Branch 1 taken 3469214 times.
7063218 if (thd_arg->time_zone_used) {
3979 /*
3980 Note that our event becomes dependent on the Time_zone object
3981 representing the time zone. Fortunately such objects are never deleted
3982 or changed during mysqld's lifetime.
3983 */
3984
1/2
✓ Branch 0 taken 62392 times.
✗ Branch 1 not taken.
124790 time_zone_len = thd_arg->variables.time_zone->get_name()->length();
3985
1/2
✓ Branch 0 taken 62393 times.
✗ Branch 1 not taken.
124786 time_zone_str = thd_arg->variables.time_zone->get_name()->ptr();
3986 } else
3987 6938428 time_zone_len = 0;
3988
3989 /*
3990 In what follows, we define in which cache, trx-cache or stmt-cache,
3991 this Query Log Event will be written to.
3992
3993 If ignore_cmd_internals is defined, we rely on the is_trans flag to
3994 choose the cache and this is done in the base class Log_event. False
3995 means that the stmt-cache will be used and upon statement commit/rollback
3996 the cache will be flushed to disk. True means that the trx-cache will
3997 be used and upon transaction commit/rollback the cache will be flushed
3998 to disk.
3999
4000 If set immediate cache is defined, for convenience, we automatically
4001 use the stmt-cache. This mean that the statement will be written
4002 to the stmt-cache and immediately flushed to disk without waiting
4003 for a commit/rollback notification.
4004
4005 For example, the cluster/ndb captures a request to execute a DDL
4006 statement and synchronously propagate it to all available MySQL
4007 servers. Unfortunately, the current protocol assumes that the
4008 generated events are immediately written to diks and does not check
4009 for commit/rollback.
4010
4011 Upon dropping a connection, DDLs (i.e. DROP TEMPORARY TABLE) are
4012 generated and in this case the statements have the immediate flag
4013 set because there is no commit/rollback.
4014
4015 If the immediate flag is not set, the decision on the cache is based
4016 on the current statement and the flag is_trans, which indicates if
4017 a transactional engine was updated.
4018
4019 Statements are classified as row producers (i.e. can_generate_row_events())
4020 or non-row producers. Non-row producers, DDL in general, are treated
4021 as the immediate flag was set and for convenience are written to the
4022 stmt-cache and immediately flushed to disk.
4023
4024 Row producers are handled in general according to the is_trans flag.
4025 False means that the stmt-cache will be used and upon statement
4026 commit/rollback the cache will be flushed to disk. True means that the
4027 trx-cache will be used and upon transaction commit/rollback the cache
4028 will be flushed to disk.
4029
4030 Unfortunately, there are exceptions to this non-row and row producer
4031 rules:
4032
4033 . The SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT does not
4034 have the flag is_trans set because there is no updated engine but
4035 must be written to the trx-cache.
4036
4037 . SET If auto-commit is on, it must not go through a cache.
4038
4039 . CREATE TABLE is classfied as non-row producer but CREATE TEMPORARY
4040 must be handled as row producer.
4041
4042 . DROP TABLE is classfied as non-row producer but DROP TEMPORARY
4043 must be handled as row producer.
4044
4045 Finally, some statements that does not have the flag is_trans set may
4046 be written to the trx-cache based on the following criteria:
4047
4048 . updated both a transactional and a non-transactional engine (i.e.
4049 stmt_has_updated_trans_table()).
4050
4051 . accessed both a transactional and a non-transactional engine and
4052 is classified as unsafe (i.e. is_mixed_stmt_unsafe()).
4053
4054 . is executed within a transaction and previously a transactional
4055 engine was updated and the flag binlog_direct_non_trans_update
4056 is set.
4057 */
4058
2/2
✓ Branch 0 taken 2654233 times.
✓ Branch 1 taken 877375 times.
7063216 if (ignore_cmd_internals) return;
4059
4060 /*
4061 true defines that the trx-cache must be used.
4062 */
4063 1754750 bool cmd_can_generate_row_events = false;
4064 /*
4065 true defines that the trx-cache must be used.
4066 */
4067 1754750 bool cmd_must_go_to_trx_cache = false;
4068
4069 1754750 LEX *lex = thd->lex;
4070
2/2
✓ Branch 0 taken 873364 times.
✓ Branch 1 taken 4011 times.
1754750 if (!immediate) {
4071
5/5
✓ Branch 0 taken 103111 times.
✓ Branch 1 taken 146032 times.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 8452 times.
✓ Branch 4 taken 615693 times.
1746728 switch (lex->sql_command) {
4072 206222 case SQLCOM_DROP_TABLE:
4073 206222 cmd_can_generate_row_events =
4074
4/4
✓ Branch 0 taken 1578 times.
✓ Branch 1 taken 101533 times.
✓ Branch 2 taken 318 times.
✓ Branch 3 taken 1260 times.
206222 lex->drop_temporary && thd->in_multi_stmt_transaction_mode();
4075 206222 break;
4076 292064 case SQLCOM_CREATE_TABLE:
4077
5/6
✓ Branch 0 taken 146032 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7577 times.
✓ Branch 3 taken 138455 times.
✓ Branch 4 taken 6359 times.
✓ Branch 5 taken 1218 times.
307218 cmd_must_go_to_trx_cache = !lex->query_block->field_list_is_empty() &&
4078 15154 thd->is_current_stmt_binlog_format_row();
4079 292064 cmd_can_generate_row_events =
4080
2/2
✓ Branch 0 taken 9522 times.
✓ Branch 1 taken 626 times.
20296 ((lex->create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
4081
4/4
✓ Branch 0 taken 10148 times.
✓ Branch 1 taken 135884 times.
✓ Branch 2 taken 6359 times.
✓ Branch 3 taken 139047 times.
312360 thd->in_multi_stmt_transaction_mode()) ||
4082 cmd_must_go_to_trx_cache;
4083 292064 break;
4084 152 case SQLCOM_SET_OPTION:
4085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
152 if (lex->autocommit)
4086 cmd_can_generate_row_events = cmd_must_go_to_trx_cache = false;
4087 else
4088 152 cmd_can_generate_row_events = true;
4089 152 break;
4090 16904 case SQLCOM_RELEASE_SAVEPOINT:
4091 case SQLCOM_ROLLBACK_TO_SAVEPOINT:
4092 case SQLCOM_SAVEPOINT:
4093 case SQLCOM_XA_PREPARE:
4094 16904 cmd_can_generate_row_events = cmd_must_go_to_trx_cache = true;
4095 16904 break;
4096 1231386 default:
4097 cmd_can_generate_row_events =
4098
1/2
✓ Branch 0 taken 615565 times.
✗ Branch 1 not taken.
1231386 sqlcom_can_generate_row_events(thd->lex->sql_command);
4099 1231130 break;
4100 }
4101 } else {
4102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4011 times.
8022 assert(!using_trans); // immediate is incompatible with using_trans
4103 }
4104
4105 /*
4106 Drop the flag as sort of reset right before the query being logged
4107 gets classified as possibly not atomic DDL.
4108 */
4109
2/2
✓ Branch 0 taken 186955 times.
✓ Branch 1 taken 690292 times.
1754494 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = false;
4110
4111
2/2
✓ Branch 0 taken 396690 times.
✓ Branch 1 taken 480557 times.
1754494 if (cmd_can_generate_row_events) {
4112
4/4
✓ Branch 0 taken 381901 times.
✓ Branch 1 taken 14789 times.
✓ Branch 2 taken 301985 times.
✓ Branch 3 taken 79916 times.
793380 cmd_must_go_to_trx_cache = cmd_must_go_to_trx_cache || using_trans;
4113 1113196 if (cmd_must_go_to_trx_cache ||
4114
3/4
✓ Branch 0 taken 79954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79220 times.
✓ Branch 3 taken 734 times.
159516 stmt_has_updated_trans_table(
4115
3/6
✓ Branch 0 taken 79758 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 318070 times.
✓ Branch 3 taken 78816 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
953670 thd->get_transaction()->ha_trx_info(Transaction_ctx::STMT)) ||
4116
3/4
✓ Branch 0 taken 79448 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79345 times.
✓ Branch 3 taken 103 times.
158390 thd->lex->is_mixed_stmt_unsafe(
4117 158384 thd->in_multi_stmt_transaction_mode(),
4118 158384 thd->variables.binlog_direct_non_trans_update,
4119
5/6
✓ Branch 0 taken 79938 times.
✓ Branch 1 taken 316752 times.
✓ Branch 2 taken 79192 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 80078 times.
✓ Branch 5 taken 316819 times.
1112110 trans_has_updated_trans_table(thd), thd->tx_isolation) ||
4120
2/2
✓ Branch 0 taken 76565 times.
✓ Branch 1 taken 2780 times.
158690 (!thd->variables.binlog_direct_non_trans_update &&
4121
3/4
✓ Branch 0 taken 76528 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 473 times.
✓ Branch 3 taken 76055 times.
153130 trans_has_updated_trans_table(thd))) {
4122 636140 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4123 636140 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4124 } else {
4125 157632 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4126 157632 event_cache_type = Log_event::EVENT_STMT_CACHE;
4127 }
4128
3/4
✓ Branch 0 taken 480769 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 332427 times.
✓ Branch 3 taken 148342 times.
961114 } else if (is_atomic_ddl(thd, using_trans)) {
4129
2/4
✓ Branch 0 taken 332427 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 332427 times.
664854 assert(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END));
4130 /*
4131 Event creation is normally followed by its logging.
4132 Todo: add exceptions if any.
4133 */
4134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332427 times.
664854 assert(!thd->is_operating_substatement_implicitly);
4135
4136 664854 Transaction_ctx *trn_ctx = thd->get_transaction();
4137
4138 /* Transaction needs to be active for xid to be assigned, */
4139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332427 times.
664854 assert(trn_ctx->is_active(Transaction_ctx::SESSION));
4140 /* and the transaction's xid has been already computed. */
4141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 332427 times.
664854 assert(!trn_ctx->xid_state()->get_xid()->is_null());
4142
4143 #ifdef WITH_WSREP
4144 /* Step below generates DDL xid. Now that DDL are atomic (mysql-8.0)
4145 DDL is also assigned a valid xid. When running in cluster mode assign
4146 wsrep-xid to ensure that sequence is maintained for DDL and DML statement.*/
4147 my_xid xid;
4148 664854 const XID *curr_xid = trn_ctx->xid_state()->get_xid();
4149
3/4
✓ Branch 0 taken 332427 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10850 times.
✓ Branch 3 taken 321577 times.
664854 if (wsrep_is_wsrep_xid(curr_xid)) {
4150
1/2
✓ Branch 0 taken 10850 times.
✗ Branch 1 not taken.
21700 xid = wsrep_xid_seqno(*curr_xid).get();
4151 } else {
4152
1/2
✓ Branch 0 taken 321577 times.
✗ Branch 1 not taken.
643154 xid = curr_xid->get_my_xid();
4153 }
4154 #else
4155 my_xid xid = trn_ctx->xid_state()->get_xid()->get_my_xid();
4156 #endif /* WITH_WSREP */
4157
4158 /*
4159 xid uniqueness: the last time used not equal to the current one
4160 */
4161
4/6
✓ Branch 0 taken 314492 times.
✓ Branch 1 taken 17935 times.
✓ Branch 2 taken 314492 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 314492 times.
664854 assert(thd->debug_binlog_xid_last.is_null() ||
4162 thd->debug_binlog_xid_last.get_my_xid() != xid);
4163
4164 664854 ddl_xid = xid;
4165 #ifndef NDEBUG
4166 664854 thd->debug_binlog_xid_last = *trn_ctx->xid_state()->get_xid();
4167 #endif
4168 664854 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4169 664854 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4170
2/2
✓ Branch 0 taken 34660 times.
✓ Branch 1 taken 113682 times.
296684 } else if (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
4171
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 34597 times.
69320 thd->lex->create_info->m_transactional_ddl) {
4172 /*
4173 When executing CREATE-TABLE-SELECT using engine that support atomic
4174 DDL's, we cache the CREATE-TABLE event using normal logging. This
4175 enables using single transaction for execution of both CREATE-TABLE
4176 and INSERT's when applying the binlog events at slave.
4177 */
4178 126 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4179 126 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4180
4181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
126 assert(ddl_xid == binary_log::INVALID_XID);
4182
4183
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 16 times.
126 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = true;
4184 } else {
4185 /*
4186 Note SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK fall into this block.
4187 Even though CREATE-TABLE sub-statement of CREATE-TABLE-SELECT in
4188 RBR makes a turn here it is logged atomically with the SELECT
4189 Rows-log event part that determines the xid of the entire group.
4190 */
4191 296558 event_logging_type = Log_event::EVENT_IMMEDIATE_LOGGING;
4192 296558 event_cache_type = Log_event::EVENT_STMT_CACHE;
4193
4194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 148279 times.
296558 assert(ddl_xid == binary_log::INVALID_XID);
4195
4196
2/2
✓ Branch 0 taken 10377 times.
✓ Branch 1 taken 137902 times.
296558 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = true;
4197 }
4198
4199 1755310 need_sql_require_primary_key = is_sql_require_primary_key_needed(lex);
4200
4201 1754844 needs_default_table_encryption = is_default_table_encryption_needed(lex);
4202
4203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 877488 times.
1754976 assert(event_cache_type != Log_event::EVENT_INVALID_CACHE);
4204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 877488 times.
1754976 assert(event_logging_type != Log_event::EVENT_INVALID_LOGGING);
4205
5/8
✓ Branch 0 taken 877599 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 877617 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 94 times.
✓ Branch 5 taken 877523 times.
✓ Branch 6 taken 88 times.
✗ Branch 7 not taken.
1754976 DBUG_PRINT("info", ("Query_log_event has flags2: %lu sql_mode: %llu",
4206 (ulong)flags2, (ulonglong)sql_mode));
4207 }
4208 #endif /* MYSQL_SERVER */
4209
4210 /**
4211 This is used by the SQL slave thread to prepare the event before execution.
4212 */
4213 3856994 Query_log_event::Query_log_event(
4214 const char *buf, const Format_description_event *description_event,
4215 3856642 Log_event_type event_type)
4216 : binary_log::Query_event(buf, description_event, event_type),
4217 Log_event(header(), footer()),
4218
1/2
✓ Branch 0 taken 1834356 times.
✗ Branch 1 not taken.
3856994 has_ddl_committed(false) {
4219
1/2
✓ Branch 0 taken 1928503 times.
✗ Branch 1 not taken.
3856996 DBUG_TRACE;
4220 3857006 data_buf = nullptr;
4221
3/4
✓ Branch 0 taken 1834486 times.
✓ Branch 1 taken 94013 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1834485 times.
3857006 if (!is_valid()) return;
4222
4223 3856996 slave_proxy_id = thread_id;
4224 3856996 exec_time = query_exec_time;
4225
4226 3856996 ulong buf_len = catalog_len + 1 + time_zone_len + 1 + user_len + 1 +
4227 3856996 host_len + 1 + data_len + 1;
4228
4229
2/4
✓ Branch 0 taken 1928498 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1928498 times.
3856996 if (!(data_buf = (Log_event_header::Byte *)my_malloc(key_memory_log_event,
4230 buf_len, MYF(MY_WME)))) {
4231 common_header->set_is_valid(false);
4232 return;
4233 }
4234 /*
4235 The data buffer is used by the slave SQL thread while applying
4236 the event. The catalog, time_zone)str, user, host, db, query
4237 are pointers to this data_buf. The function call below, points these
4238 const pointers to the data buffer.
4239 */
4240
2/4
✓ Branch 0 taken 1928496 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1928496 times.
3856996 if (!(fill_data_buf(data_buf, buf_len))) {
4241 common_header->set_is_valid(false);
4242 return;
4243 }
4244
4245
2/4
✓ Branch 0 taken 1928497 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1928499 times.
✗ Branch 3 not taken.
3856992 common_header->set_is_valid(query != nullptr && q_len > 0);
4246
2/2
✓ Branch 0 taken 1928504 times.
✓ Branch 1 taken 1 times.
3856990 }
4247
4248 #ifndef MYSQL_SERVER
4249 /**
4250 Given a timestamp (microseconds since epoch), generate a string
4251 of the form YYYY-MM-DD HH:MM:SS.UUUUUU and return the length.
4252
4253 @param timestamp timestamp to convert to string.
4254 @param buf Buffer to which timestamp will be written as a string.
4255 @return The length of the string containing the converted timestamp
4256 */
4257 67870 inline size_t microsecond_timestamp_to_str(ulonglong timestamp, char *buf) {
4258 67870 time_t seconds = (time_t)(timestamp / 1000000);
4259 67870 int useconds = (int)(timestamp % 1000000);
4260 struct tm time_struct;
4261 67870 localtime_r(&seconds, &time_struct);
4262 67870 size_t length = strftime(buf, 255, "%F %T", &time_struct);
4263 67870 length += sprintf(buf + length, ".%06d", useconds);
4264 67870 length += strftime(buf + length, 255, " %Z", &time_struct);
4265 67870 return length;
4266 }
4267
4268 /**
4269 Query_log_event::print().
4270
4271 @todo
4272 print the catalog ??
4273 */
4274 88491 void Query_log_event::print_query_header(
4275 IO_CACHE *file, PRINT_EVENT_INFO *print_event_info) const {
4276 // TODO: print the catalog ??
4277 char buff[48], *end; // Enough for "SET TIMESTAMP=1305535348.123456"
4278 char quoted_id[1 + 2 * FN_REFLEN + 2];
4279 88491 size_t quoted_len = 0;
4280 88491 bool different_db = true;
4281 uint32 tmp;
4282
4283
2/2
✓ Branch 0 taken 87059 times.
✓ Branch 1 taken 1432 times.
88491 if (!print_event_info->short_form) {
4284 87059 const char xid_assign[] = "\tXid = ";
4285 87059 char xid_buf[64 + sizeof(xid_assign) - 1] = {0};
4286
2/2
✓ Branch 0 taken 5460 times.
✓ Branch 1 taken 81599 times.
87059 if (ddl_xid != binary_log::INVALID_XID) {
4287 5460 strcpy(xid_buf, xid_assign);
4288
1/2
✓ Branch 0 taken 5460 times.
✗ Branch 1 not taken.
5460 longlong10_to_str(ddl_xid, xid_buf + strlen(xid_assign), 10);
4289 }
4290
1/2
✓ Branch 0 taken 87059 times.
✗ Branch 1 not taken.
87059 print_header(file, print_event_info, false);
4291
1/2
✓ Branch 0 taken 87059 times.
✗ Branch 1 not taken.
87059 my_b_printf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d%s\n",
4292 87059 get_type_str(), (ulong)thread_id, (ulong)exec_time, error_code,
4293 xid_buf);
4294 }
4295
4296
2/2
✓ Branch 0 taken 30444 times.
✓ Branch 1 taken 58047 times.
88491 if ((common_header->flags & LOG_EVENT_SUPPRESS_USE_F)) {
4297
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 30188 times.
30444 if (!is_trans_keyword()) print_event_info->db[0] = '\0';
4298
1/2
✓ Branch 0 taken 58047 times.
✗ Branch 1 not taken.
58047 } else if (db) {
4299
1/2
✓ Branch 0 taken 58047 times.
✗ Branch 1 not taken.
58047 quoted_len = my_strmov_quoted_identifier((char *)quoted_id, db);
4300 58047 quoted_id[quoted_len] = '\0';
4301 58047 different_db = memcmp(print_event_info->db, db, db_len + 1);
4302
2/2
✓ Branch 0 taken 1987 times.
✓ Branch 1 taken 56060 times.
58047 if (different_db) memcpy(print_event_info->db, db, db_len + 1);
4303
4/4
✓ Branch 0 taken 57873 times.
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 1816 times.
✓ Branch 3 taken 56057 times.
58047 if (db[0] && different_db)
4304
1/2
✓ Branch 0 taken 1816 times.
✗ Branch 1 not taken.
1816 my_b_printf(file, "use %s%s\n", quoted_id, print_event_info->delimiter);
4305 }
4306
4307
1/2
✓ Branch 0 taken 88491 times.
✗ Branch 1 not taken.
88491 end = longlong10_to_str(common_header->when.tv_sec,
4308 my_stpcpy(buff, "SET TIMESTAMP="), 10);
4309
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 88421 times.
88491 if (common_header->when.tv_usec)
4310 70 end += sprintf(end, ".%06d", (int)common_header->when.tv_usec);
4311 88491 end = my_stpcpy(end, print_event_info->delimiter);
4312 88491 *end++ = '\n';
4313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88491 times.
88491 assert(end < buff + sizeof(buff));
4314 [[maybe_unused]]
4315
1/2
✓ Branch 0 taken 88491 times.
✗ Branch 1 not taken.
88491 int write_res = my_b_write(file, (uchar *)buff, (uint)(end - buff));
4316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88491 times.
88491 assert(write_res == 0);
4317
2/2
✓ Branch 0 taken 88471 times.
✓ Branch 1 taken 20 times.
88491 if (!print_event_info->require_row_format &&
4318
2/2
✓ Branch 0 taken 83659 times.
✓ Branch 1 taken 4812 times.
88471 (!print_event_info->thread_id_printed ||
4319
2/2
✓ Branch 0 taken 593 times.
✓ Branch 1 taken 83066 times.
83659 ((common_header->flags & LOG_EVENT_THREAD_SPECIFIC_F) &&
4320
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 510 times.
593 thread_id != print_event_info->thread_id))) {
4321 // If --short-form, print deterministic value instead of pseudo_thread_id.
4322
1/2
✓ Branch 0 taken 4895 times.
✗ Branch 1 not taken.
4895 my_b_printf(file, "SET @@session.pseudo_thread_id=%lu%s\n",
4323 4719 short_form ? 999999999 : (ulong)thread_id,
4324
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 4719 times.
4895 print_event_info->delimiter);
4325 4895 print_event_info->thread_id = thread_id;
4326 4895 print_event_info->thread_id_printed = true;
4327 }
4328
4329 /*
4330 If flags2_inited==0, this is an event from 3.23 or 4.0; nothing to
4331 print (remember we don't produce mixed relay logs so there cannot be
4332 5.0 events before that one so there is nothing to reset).
4333 */
4334
1/2
✓ Branch 0 taken 88491 times.
✗ Branch 1 not taken.
88491 if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */
4335 {
4336 /* tmp is a bitmask of bits which have changed. */
4337
2/2
✓ Branch 0 taken 83668 times.
✓ Branch 1 taken 4823 times.
88491 if (likely(print_event_info->flags2_inited))
4338 /* All bits which have changed */
4339 83668 tmp = (print_event_info->flags2) ^ flags2;
4340 else /* that's the first Query event we read */
4341 {
4342 4823 print_event_info->flags2_inited = true;
4343 4823 tmp = ~((uint32)0); /* all bits have changed */
4344 }
4345
4346
2/2
✓ Branch 0 taken 4829 times.
✓ Branch 1 taken 83662 times.
88491 if (unlikely(tmp)) /* some bits have changed */
4347 {
4348 4829 bool need_comma = false;
4349
1/2
✓ Branch 0 taken 4829 times.
✗ Branch 1 not taken.
4829 my_b_printf(file, "SET ");
4350
1/2
✓ Branch 0 taken 4829 times.
✗ Branch 1 not taken.
4829 print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2,
4351 "@@session.foreign_key_checks", &need_comma);
4352
1/2
✓ Branch 0 taken 4829 times.
✗ Branch 1 not taken.
4829 print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2,
4353 "@@session.sql_auto_is_null", &need_comma);
4354
1/2
✓ Branch 0 taken 4829 times.
✗ Branch 1 not taken.
4829 print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2,
4355 "@@session.unique_checks", &need_comma);
4356
1/2
✓ Branch 0 taken 4829 times.
✗ Branch 1 not taken.
4829 print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2,
4357 "@@session.autocommit", &need_comma);
4358
1/2
✓ Branch 0 taken 4829 times.
✗ Branch 1 not taken.
4829 my_b_printf(file, "%s\n", print_event_info->delimiter);
4359 4829 print_event_info->flags2 = flags2;
4360 }
4361 }
4362
4363 /*
4364 Now the session variables;
4365 it's more efficient to pass SQL_MODE as a number instead of a
4366 comma-separated list.
4367 FOREIGN_KEY_CHECKS, SQL_AUTO_IS_NULL, UNIQUE_CHECKS are session-only
4368 variables (they have no global version; they're not listed in
4369 sql_class.h), The tests below work for pure binlogs or pure relay
4370 logs. Won't work for mixed relay logs but we don't create mixed
4371 relay logs (that is, there is no relay log with a format change
4372 except within the 3 first events, which mysqlbinlog handles
4373 gracefully). So this code should always be good.
4374 */
4375
4376
5/6
✓ Branch 0 taken 88491 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5339 times.
✓ Branch 3 taken 83152 times.
✓ Branch 4 taken 5339 times.
✓ Branch 5 taken 83152 times.
176982 if (likely(sql_mode_inited) &&
4377
2/2
✓ Branch 0 taken 83166 times.
✓ Branch 1 taken 5325 times.
171657 (unlikely(print_event_info->sql_mode != sql_mode ||
4378
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 83152 times.
83166 !print_event_info->sql_mode_inited))) {
4379 /*
4380 All the SQL_MODEs included in 0x1003ff00 were removed in 8.0.5. The
4381 upgrade procedure clears these bits. So the bits can only be set on older
4382 binlogs. Therefore, we generate this version-conditioned expression that
4383 masks out the removed modes in case this is executed on 8.0.5 or later.
4384 */
4385 5339 const char *mask = "";
4386
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 5303 times.
5339 if (sql_mode & 0x1003ff00) mask = "/*!80005 &~0x1003ff00*/";
4387 5339 my_b_printf(file, "SET @@session.sql_mode=%lu%s%s\n", (ulong)sql_mode, mask,
4388
1/2
✓ Branch 0 taken 5339 times.
✗ Branch 1 not taken.
5339 print_event_info->delimiter);
4389 5339 print_event_info->sql_mode = sql_mode;
4390 5339 print_event_info->sql_mode_inited = true;
4391 }
4392
2/2
✓ Branch 0 taken 83654 times.
✓ Branch 1 taken 4837 times.
88491 if (print_event_info->auto_increment_increment != auto_increment_increment ||
4393
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 83618 times.
83654 print_event_info->auto_increment_offset != auto_increment_offset) {
4394 4873 my_b_printf(file,
4395 "SET @@session.auto_increment_increment=%u, "
4396 "@@session.auto_increment_offset=%u%s\n",
4397 4873 auto_increment_increment, auto_increment_offset,
4398
1/2
✓ Branch 0 taken 4873 times.
✗ Branch 1 not taken.
4873 print_event_info->delimiter);
4399 4873 print_event_info->auto_increment_increment = auto_increment_increment;
4400 4873 print_event_info->auto_increment_offset = auto_increment_offset;
4401 }
4402
4403 /* TODO: print the catalog when we feature SET CATALOG */
4404
4405
5/6
✓ Branch 0 taken 88491 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4839 times.
✓ Branch 3 taken 83652 times.
✓ Branch 4 taken 4839 times.
✓ Branch 5 taken 83652 times.
176982 if (likely(charset_inited) &&
4406
2/2
✓ Branch 0 taken 83668 times.
✓ Branch 1 taken 4823 times.
172159 (unlikely(!print_event_info->charset_inited ||
4407
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 83652 times.
83668 memcmp(print_event_info->charset, charset, 6)))) {
4408 4839 const char *charset_p = charset; // Avoid type-punning warning.
4409
1/2
✓ Branch 0 taken 4839 times.
✗ Branch 1 not taken.
4839 CHARSET_INFO *cs_info = get_charset(uint2korr(charset_p), MYF(MY_WME));
4410
1/2
✓ Branch 0 taken 4839 times.
✗ Branch 1 not taken.
4839 if (cs_info) {
4411 /* for mysql client */
4412 4839 my_b_printf(file, "/*!\\C %s */%s\n", cs_info->csname,
4413
1/2
✓ Branch 0 taken 4839 times.
✗ Branch 1 not taken.
4839 print_event_info->delimiter);
4414 }
4415
1/2
✓ Branch 0 taken 4839 times.
✗ Branch 1 not taken.
4839 my_b_printf(file,
4416 "SET "
4417 "@@session.character_set_client=%d,"
4418 "@@session.collation_connection=%d,"
4419 "@@session.collation_server=%d"
4420 "%s\n",
4421 4839 uint2korr(charset_p), uint2korr(charset + 2),
4422 4839 uint2korr(charset + 4), print_event_info->delimiter);
4423 4839 memcpy(print_event_info->charset, charset, 6);
4424 4839 print_event_info->charset_inited = true;
4425 }
4426
2/2
✓ Branch 0 taken 1160 times.
✓ Branch 1 taken 87331 times.
88491 if (time_zone_len) {
4427 1160 if (memcmp(print_event_info->time_zone_str, time_zone_str,
4428
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 698 times.
1160 time_zone_len + 1)) {
4429 462 my_b_printf(file, "SET @@session.time_zone='%s'%s\n", time_zone_str,
4430
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
462 print_event_info->delimiter);
4431 462 memcpy(print_event_info->time_zone_str, time_zone_str, time_zone_len + 1);
4432 }
4433 }
4434
2/2
✓ Branch 0 taken 4825 times.
✓ Branch 1 taken 83666 times.
88491 if (lc_time_names_number != print_event_info->lc_time_names_number) {
4435 4825 my_b_printf(file, "SET @@session.lc_time_names=%d%s\n",
4436
1/2
✓ Branch 0 taken 4825 times.
✗ Branch 1 not taken.
4825 lc_time_names_number, print_event_info->delimiter);
4437 4825 print_event_info->lc_time_names_number = lc_time_names_number;
4438 }
4439
2/2
✓ Branch 0 taken 4829 times.
✓ Branch 1 taken 83662 times.
88491 if (charset_database_number != print_event_info->charset_database_number) {
4440
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4822 times.
4829 if (charset_database_number)
4441 7 my_b_printf(file, "SET @@session.collation_database=%d%s\n",
4442
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 charset_database_number, print_event_info->delimiter);
4443 else
4444 4822 my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n",
4445
1/2
✓ Branch 0 taken 4822 times.
✗ Branch 1 not taken.
4822 print_event_info->delimiter);
4446 4829 print_event_info->charset_database_number = charset_database_number;
4447 }
4448
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 88464 times.
88491 if (explicit_defaults_ts != TERNARY_UNSET)
4449 27 my_b_printf(file, "SET @@session.explicit_defaults_for_timestamp=%d%s\n",
4450 27 explicit_defaults_ts == TERNARY_OFF ? 0 : 1,
4451
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 print_event_info->delimiter);
4452 88491 if (default_collation_for_utf8mb4_number !=
4453
2/2
✓ Branch 0 taken 4823 times.
✓ Branch 1 taken 83668 times.
88491 print_event_info->default_collation_for_utf8mb4_number) {
4454
2/2
✓ Branch 0 taken 4806 times.
✓ Branch 1 taken 17 times.
4823 if (default_collation_for_utf8mb4_number)
4455 4806 my_b_printf(
4456 file, "/*!80011 SET @@session.default_collation_for_utf8mb4=%d*/%s\n",
4457
1/2
✓ Branch 0 taken 4806 times.
✗ Branch 1 not taken.
4806 default_collation_for_utf8mb4_number, print_event_info->delimiter);
4458 4823 print_event_info->default_collation_for_utf8mb4_number =
4459 4823 default_collation_for_utf8mb4_number;
4460 }
4461
2/2
✓ Branch 0 taken 2787 times.
✓ Branch 1 taken 85704 times.
88491 if (sql_require_primary_key != print_event_info->sql_require_primary_key) {
4462 2787 my_b_printf(file, "/*!80013 SET @@session.sql_require_primary_key=%d*/%s\n",
4463
1/2
✓ Branch 0 taken 2787 times.
✗ Branch 1 not taken.
2787 sql_require_primary_key, print_event_info->delimiter);
4464 }
4465
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 88365 times.
88491 if (default_table_encryption != print_event_info->default_table_encryption) {
4466 126 my_b_printf(file,
4467 "/*!80016 SET @@session.default_table_encryption=%d*/%s\n",
4468
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 default_table_encryption, print_event_info->delimiter);
4469 }
4470
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 88459 times.
88491 if (ddl_skip_rewrite != print_event_info->ddl_skip_rewrite) {
4471 32 my_b_printf(file, "/*!80026 SET @@session.binlog_ddl_skip_rewrite=%d*/%s\n",
4472
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 ddl_skip_rewrite, print_event_info->delimiter);
4473 32 print_event_info->ddl_skip_rewrite = ddl_skip_rewrite;
4474 }
4475 88491 }
4476
4477 88455 void Query_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
4478 88455 IO_CACHE *const head = &print_event_info->head_cache;
4479
4480 /**
4481 reduce the size of io cache so that the write function is called
4482 for every call to my_b_write().
4483 */
4484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88455 times.
88455 DBUG_EXECUTE_IF("simulate_file_write_error",
4485 { head->write_pos = head->write_end - 500; });
4486 88455 print_query_header(head, print_event_info);
4487 [[maybe_unused]]
4488 88455 int write_res = my_b_write(head, pointer_cast<const uchar *>(query), q_len);
4489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88455 times.
88455 assert(write_res == 0);
4490 88455 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
4491 88455 }
4492 #endif /* !MYSQL_SERVER */
4493
4494 #if defined(MYSQL_SERVER)
4495
4496 /**
4497 Associating slave Worker thread to a subset of temporary tables.
4498
4499 @param thd_arg THD instance pointer
4500 @param rli Relay_log_info of the worker
4501 */
4502 556807 void Query_log_event::attach_temp_tables_worker(THD *thd_arg,
4503 const Relay_log_info *rli) {
4504
2/2
✓ Branch 0 taken 556895 times.
✓ Branch 1 taken 10 times.
556807 if (!is_skip_temp_tables_handling_by_worker())
4505 556895 rli->current_mts_submode->attach_temp_tables(thd_arg, rli, this);
4506 556789 }
4507
4508 /**
4509 Dissociating slave Worker thread from its thd->temporary_tables
4510 to possibly update the involved entries of db-to-worker hash
4511 with new values of temporary_tables.
4512
4513 @param thd_arg THD instance pointer
4514 @param rli relay log info of the worker thread
4515 */
4516 3214 void Query_log_event::detach_temp_tables_worker(THD *thd_arg,
4517 const Relay_log_info *rli) {
4518
1/2
✓ Branch 0 taken 3214 times.
✗ Branch 1 not taken.
3214 if (!is_skip_temp_tables_handling_by_worker())
4519 3214 rli->current_mts_submode->detach_temp_tables(thd_arg, rli, this);
4520 3214 }
4521
4522 /*
4523 Query_log_event::do_apply_event()
4524 */
4525 556635 int Query_log_event::do_apply_event(Relay_log_info const *rli) {
4526 556635 return do_apply_event(rli, query, q_len);
4527 }
4528
4529 /*
4530 is_silent_error
4531
4532 Return true if the thread has an error which should be
4533 handled silently
4534 */
4535
4536 1681 static bool is_silent_error(THD *thd) {
4537
1/2
✓ Branch 0 taken 1681 times.
✗ Branch 1 not taken.
1681 DBUG_TRACE;
4538 Diagnostics_area::Sql_condition_iterator it =
4539
1/2
✓ Branch 0 taken 1681 times.
✗ Branch 1 not taken.
1681 thd->get_stmt_da()->sql_conditions();
4540 const Sql_condition *err;
4541
3/4
✓ Branch 0 taken 3379 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1698 times.
✓ Branch 3 taken 1681 times.
3379 while ((err = it++)) {
4542
3/8
✓ Branch 0 taken 1698 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1698 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1698 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1698 DBUG_PRINT("info", ("has condition %d %s", err->mysql_errno(),
4543 err->message_text()));
4544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1698 times.
1698 switch (err->mysql_errno()) {
4545 case ER_SLAVE_SILENT_RETRY_TRANSACTION: {
4546 return true;
4547 }
4548 1698 default:
4549 1698 break;
4550 }
4551 }
4552 1681 return false;
4553 1681 }
4554
4555 /**
4556 @todo
4557 Compare the values of "affected rows" around here. Something
4558 like:
4559 @code
4560 if ((uint32) affected_in_event != (uint32) affected_on_slave)
4561 {
4562 sql_print_error("Slave: did not get the expected number of affected "
4563 "rows running query from master - expected %d, got %d (this numbers "
4564 "should have matched modulo 4294967296).", 0, ...);
4565 thd->query_error = 1;
4566 }
4567 @endcode
4568 We may also want an option to tell the slave to ignore "affected"
4569 mismatch. This mismatch could be implemented with a new ER_ code, and
4570 to ignore it you would use --replica-skip-errors...
4571 */
4572 556754 int Query_log_event::do_apply_event(Relay_log_info const *rli,
4573 const char *query_arg, size_t q_len_arg) {
4574
1/2
✓ Branch 0 taken 557031 times.
✗ Branch 1 not taken.
556754 DBUG_TRACE;
4575 557031 int expected_error, actual_error = 0;
4576
4577
3/8
✓ Branch 0 taken 556916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 557004 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 557004 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
557031 DBUG_PRINT("info", ("query=%s, q_len_arg=%lu", query,
4578 static_cast<unsigned long>(q_len_arg)));
4579
4580 /*
4581 Colleagues: please never free(thd->catalog) in MySQL. This would
4582 lead to bugs as here thd->catalog is a part of an allocated block,
4583 not an entire allocated block (see
4584 Query_log_event::do_apply_event()). Same for thd->db().str. Thank
4585 you.
4586 */
4587
4588
2/2
✓ Branch 0 taken 533938 times.
✓ Branch 1 taken 23067 times.
557005 if (catalog_len) {
4589 533938 LEX_CSTRING catalog_lex_cstr = {catalog, catalog_len};
4590 533938 thd->set_catalog(catalog_lex_cstr);
4591 } else
4592 23067 thd->set_catalog(EMPTY_CSTR);
4593
4594 bool need_inc_rewrite_db_filter_counter;
4595 size_t valid_len;
4596 bool len_error;
4597 bool is_invalid_db_name =
4598
1/2
✓ Branch 0 taken 556901 times.
✗ Branch 1 not taken.
556922 validate_string(system_charset_info, db, db_len, &valid_len, &len_error);
4599
4600
3/12
✓ Branch 0 taken 556902 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 556943 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 556943 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
556901 DBUG_PRINT("debug", ("is_invalid_db_name= %s, valid_len=%zu, len_error=%s",
4601 is_invalid_db_name ? "true" : "false", valid_len,
4602 len_error ? "true" : "false"));
4603
4604
4/4
✓ Branch 0 taken 556830 times.
✓ Branch 1 taken 113 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 556790 times.
556943 if (is_invalid_db_name || len_error) {
4605 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4606
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
153 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4607 "Invalid database name in Query event.");
4608 thd->is_slave_error = true;
4609 goto end;
4610 }
4611
4612
1/2
✓ Branch 0 taken 557004 times.
✗ Branch 1 not taken.
556790 need_inc_rewrite_db_filter_counter = set_thd_db(thd, db, db_len);
4613
4614 /*
4615 Setting the character set and collation of the current database thd->db.
4616 */
4617
2/4
✓ Branch 0 taken 557103 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 557103 times.
557004 if (get_default_db_collation(thd, thd->db().str, &thd->db_charset)) {
4618 assert(thd->is_error() || thd->killed);
4619 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
4620 "Error in get_default_db_collation: %s",
4621 thd->get_stmt_da()->message_text());
4622 thd->is_slave_error = true;
4623 goto end;
4624 }
4625
4626
1/2
✓ Branch 0 taken 557104 times.
✗ Branch 1 not taken.
557103 thd->db_charset = thd->db_charset ? thd->db_charset : thd->collation();
4627
4628 557104 thd->variables.auto_increment_increment = auto_increment_increment;
4629 557104 thd->variables.auto_increment_offset = auto_increment_offset;
4630
2/2
✓ Branch 0 taken 16622 times.
✓ Branch 1 taken 540482 times.
557104 if (explicit_defaults_ts != TERNARY_UNSET)
4631 16622 thd->variables.explicit_defaults_for_timestamp =
4632 16622 explicit_defaults_ts == TERNARY_OFF ? false : true;
4633
4634 /*
4635 todo: such cleanup should not be specific to Query event and therefore
4636 is preferable at a common with other event pre-execution point
4637 */
4638
1/2
✓ Branch 0 taken 557103 times.
✗ Branch 1 not taken.
557104 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
4639
1/2
✓ Branch 0 taken 557099 times.
✗ Branch 1 not taken.
557103 thd->get_stmt_da()->reset_diagnostics_area();
4640 557099 thd->get_stmt_da()->reset_statement_cond_count();
4641
4642
3/4
✓ Branch 0 taken 97706 times.
✓ Branch 1 taken 459359 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 97706 times.
557065 if (strcmp("COMMIT", query) == 0 && rli->tables_to_lock != nullptr) {
4643 /*
4644 Cleaning-up the last statement context:
4645 the terminal event of the current statement flagged with
4646 STMT_END_F got filtered out in ndb circular replication.
4647 */
4648 int error;
4649 char llbuff[22];
4650 if ((error =
4651 rows_event_stmt_cleanup(const_cast<Relay_log_info *>(rli), thd))) {
4652 const_cast<Relay_log_info *>(rli)->report(
4653 ERROR_LEVEL, error,
4654 "Error in cleaning up after an event preceding the commit; "
4655 "the group log file/position: %s %s",
4656 const_cast<Relay_log_info *>(rli)->get_group_master_log_name_info(),
4657 llstr(const_cast<Relay_log_info *>(rli)
4658 ->get_group_master_log_pos_info(),
4659 llbuff));
4660 }
4661 /*
4662 Executing a part of rli->stmt_done() logics that does not deal
4663 with group position change. The part is redundant now but is
4664 future-change-proof addon, e.g if COMMIT handling will start checking
4665 invariants like IN_STMT flag must be off at committing the transaction.
4666 */
4667 const_cast<Relay_log_info *>(rli)->inc_event_relay_log_pos();
4668 const_cast<Relay_log_info *>(rli)->clear_flag(Relay_log_info::IN_STMT);
4669 } else {
4670
1/2
✓ Branch 0 taken 557000 times.
✗ Branch 1 not taken.
557065 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
4671 }
4672
4673 {
4674
1/2
✓ Branch 0 taken 556794 times.
✗ Branch 1 not taken.
557000 Applier_security_context_guard security_context{rli, thd};
4675
2/2
✓ Branch 0 taken 521051 times.
✓ Branch 1 taken 35743 times.
556794 if (!thd->variables.require_row_format) {
4676
1/2
✓ Branch 0 taken 521048 times.
✗ Branch 1 not taken.
521051 if (!security_context.skip_priv_checks() &&
4677
3/4
✓ Branch 0 taken 326 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 170 times.
326 !security_context.has_access({SUPER_ACL}) &&
4678
5/6
✓ Branch 0 taken 326 times.
✓ Branch 1 taken 520722 times.
✓ Branch 2 taken 156 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 133 times.
✓ Branch 5 taken 23 times.
521327 !security_context.has_access({"SYSTEM_VARIABLES_ADMIN"}) &&
4679
3/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 520858 times.
521001 !security_context.has_access({"SESSION_VARIABLES_ADMIN"})) {
4680
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 rli->report(ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4681
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4682 "SUPER, SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
4683 10 thd->is_slave_error = true;
4684 10 goto end;
4685 }
4686 520858 thd->variables.pseudo_thread_id = thread_id; // for temp tables
4687 }
4688
4689
1/2
✓ Branch 0 taken 556814 times.
✗ Branch 1 not taken.
556601 thd->set_time(&(common_header->when));
4690
1/2
✓ Branch 0 taken 557057 times.
✗ Branch 1 not taken.
556814 thd->set_query(query_arg, q_len_arg);
4691
1/2
✓ Branch 0 taken 557059 times.
✗ Branch 1 not taken.
557057 thd->set_query_for_display(query_arg, q_len_arg);
4692
1/2
✓ Branch 0 taken 557008 times.
✗ Branch 1 not taken.
557059 thd->set_query_id(next_query_id());
4693
1/2
✓ Branch 0 taken 556784 times.
✗ Branch 1 not taken.
557008 attach_temp_tables_worker(thd, rli);
4694
3/10
✓ Branch 0 taken 556928 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 556967 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 556967 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
556784 DBUG_PRINT("query", ("%s", thd->query().str));
4695
4696
3/4
✓ Branch 0 taken 556876 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 556873 times.
556967 DBUG_EXECUTE_IF("simulate_error_in_ddl", error_code = 1051;);
4697
4698
3/6
✓ Branch 0 taken 556716 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 556722 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 556871 times.
✗ Branch 5 not taken.
1113574 if (ignored_error_code((expected_error = error_code)) ||
4699
1/2
✓ Branch 0 taken 556731 times.
✗ Branch 1 not taken.
556722 !unexpected_error_code(expected_error)) {
4700
1/2
✓ Branch 0 taken 556893 times.
✗ Branch 1 not taken.
556871 if (flags2_inited)
4701 /*
4702 all bits of thd->variables.option_bits which are 1 in
4703 OPTIONS_WRITTEN_TO_BIN_LOG must take their value from flags2.
4704 */
4705 556893 thd->variables.option_bits =
4706 556893 flags2 | (thd->variables.option_bits & ~OPTIONS_WRITTEN_TO_BIN_LOG);
4707 /*
4708 else, we are in a 3.23/4.0 binlog; we previously received a
4709 Rotate_log_event which reset thd->variables.option_bits and sql_mode
4710 etc, so nothing to do.
4711 */
4712 /*
4713 We do not replicate MODE_NO_DIR_IN_CREATE. That is, if the master is a
4714 slave which runs with SQL_MODE=MODE_NO_DIR_IN_CREATE, this should not
4715 force us to ignore the dir too. Imagine you are a ring of machines, and
4716 one has a disk problem so that you temporarily need
4717 MODE_NO_DIR_IN_CREATE on this machine; you don't want it to propagate
4718 elsewhere (you don't want all slaves to start ignoring the dirs).
4719 */
4720
1/2
✓ Branch 0 taken 556911 times.
✗ Branch 1 not taken.
556871 if (sql_mode_inited) {
4721 /*
4722 All the SQL_MODEs included in 0x1003ff00 were removed in 8.0.5.
4723 The upgrade procedure clears these bits. So the bits can only be set
4724 when replicating from an older server. We consider it safe to clear
4725 the bits, because:
4726 (1) all these bits except MAXDB has zero impact on replicated
4727 statements, and MAXDB has minimal impact only;
4728 (2) the upgrade-pre-check script warns when the bit is set, so we
4729 assume users have verified that it is safe to ignore the bit.
4730 */
4731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556911 times.
556911 if (sql_mode & ~(MODE_ALLOWED_MASK | MODE_IGNORED_MASK)) {
4732 my_error(ER_UNSUPPORTED_SQL_MODE, MYF(0),
4733 sql_mode & ~(MODE_ALLOWED_MASK | MODE_IGNORED_MASK));
4734 1 goto compare_errors;
4735 }
4736 556911 sql_mode &= MODE_ALLOWED_MASK;
4737 556911 thd->variables.sql_mode =
4738 556911 (sql_mode_t)((thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) |
4739 556911 (sql_mode & ~(ulonglong)MODE_NO_DIR_IN_CREATE));
4740 }
4741
2/2
✓ Branch 0 taken 556750 times.
✓ Branch 1 taken 121 times.
556871 if (charset_inited) {
4742
3/4
✓ Branch 0 taken 557045 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11373 times.
✓ Branch 3 taken 545672 times.
556750 if (rli->cached_charset_compare(charset)) {
4743 11373 const char *charset_p = charset; // Avoid type-punning warning.
4744 /* Verify that we support the charsets found in the event. */
4745 34118 if (!(thd->variables.character_set_client =
4746
1/2
✓ Branch 0 taken 11372 times.
✗ Branch 1 not taken.
11373 get_charset(uint2korr(charset_p), MYF(MY_WME))) ||
4747 22744 !(thd->variables.collation_connection =
4748
4/8
✓ Branch 0 taken 11372 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11372 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11373 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 11373 times.
22746 get_charset(uint2korr(charset + 2), MYF(MY_WME))) ||
4749 22747 !(thd->variables.collation_server =
4750
3/4
✓ Branch 0 taken 11374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 11373 times.
11373 get_charset(uint2korr(charset + 4), MYF(MY_WME)))) {
4751 /*
4752 We updated the thd->variables with nonsensical values (0). Let's
4753 set them to something safe (i.e. which avoids crash), and we'll
4754 stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
4755 ignore this error).
4756 */
4757 set_slave_thread_default_charset(thd, rli);
4758 goto compare_errors;
4759 }
4760
1/2
✓ Branch 0 taken 11373 times.
✗ Branch 1 not taken.
11373 thd->update_charset(); // for the charset change to take effect
4761 /*
4762 We cannot ask for parsing a statement using a character set
4763 without state_maps (parser internal data).
4764 */
4765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11373 times.
11373 if (!thd->variables.character_set_client->state_maps) {
4766 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4767 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4768 "character_set cannot be parsed");
4769 thd->is_slave_error = true;
4770 goto end;
4771 }
4772 /*
4773 Reset thd->query_string.cs to the newly set value.
4774 Note, there is a small flaw here. For a very short time frame
4775 if the new charset is different from the old charset and
4776 if another thread executes "SHOW PROCESSLIST" after
4777 the above thd->set_query() and before this thd->set_query(),
4778 and if the current query has some non-ASCII characters,
4779 the another thread may see some '?' marks in the PROCESSLIST
4780 result. This should be acceptable now. This is a reminder
4781 to fix this if any refactoring happens here sometime.
4782 */
4783
1/2
✓ Branch 0 taken 11373 times.
✗ Branch 1 not taken.
11373 thd->set_query(query_arg, q_len_arg);
4784
1/2
✓ Branch 0 taken 10828 times.
✗ Branch 1 not taken.
11373 thd->reset_query_for_display();
4785 }
4786 }
4787
2/2
✓ Branch 0 taken 21260 times.
✓ Branch 1 taken 535361 times.
556621 if (time_zone_len) {
4788 21260 String tmp(time_zone_str, time_zone_len, &my_charset_bin);
4789
3/4
✓ Branch 0 taken 21261 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 21260 times.
21260 if (!(thd->variables.time_zone = my_tz_find(thd, &tmp))) {
4790
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
4791 1 thd->variables.time_zone = global_system_variables.time_zone;
4792 1 goto compare_errors;
4793 }
4794
2/2
✓ Branch 0 taken 21260 times.
✓ Branch 1 taken 1 times.
21261 }
4795
2/2
✓ Branch 0 taken 1023 times.
✓ Branch 1 taken 555598 times.
556621 if (lc_time_names_number) {
4796 2046 if (!(thd->variables.lc_time_names =
4797
2/4
✓ Branch 0 taken 1023 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1023 times.
1023 my_locale_by_number(lc_time_names_number))) {
4798 my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%d'", MYF(0),
4799 lc_time_names_number);
4800 thd->variables.lc_time_names = &my_locale_en_US;
4801 goto compare_errors;
4802 }
4803 } else
4804 555598 thd->variables.lc_time_names = &my_locale_en_US;
4805
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 556009 times.
556621 if (charset_database_number) {
4806 CHARSET_INFO *cs;
4807
2/4
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 612 times.
612 if (!(cs = get_charset(charset_database_number, MYF(0)))) {
4808 char buf[20];
4809 longlong10_to_str(charset_database_number, buf, 10);
4810 my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
4811 goto compare_errors;
4812 }
4813 612 thd->variables.collation_database = cs;
4814 } else
4815 556009 thd->variables.collation_database = thd->db_charset;
4816
1/2
✓ Branch 0 taken 556641 times.
✗ Branch 1 not taken.
556621 if (default_collation_for_utf8mb4_number) {
4817 CHARSET_INFO *cs;
4818
2/4
✓ Branch 0 taken 556580 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 556580 times.
556641 if (!(cs = get_charset(default_collation_for_utf8mb4_number, MYF(0)))) {
4819 char buf[20];
4820 longlong10_to_str(default_collation_for_utf8mb4_number, buf, 10);
4821 my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
4822 goto compare_errors;
4823 }
4824 556580 thd->variables.default_collation_for_utf8mb4 = cs;
4825 } else
4826 // The transaction was replicated from a server with utf8mb4_general_ci
4827 // as default collation for utf8mb4 (versions 5.7-)
4828 thd->variables.default_collation_for_utf8mb4 =
4829 &my_charset_utf8mb4_general_ci;
4830
4831
4/4
✓ Branch 0 taken 14509 times.
✓ Branch 1 taken 542051 times.
✓ Branch 2 taken 14504 times.
✓ Branch 3 taken 542056 times.
571069 if (sql_require_primary_key != 0xff &&
4832 Relay_log_info::PK_CHECK_STREAM ==
4833
3/4
✓ Branch 0 taken 14509 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14504 times.
✓ Branch 3 taken 5 times.
14509 rli->get_require_table_primary_key_check()) {
4834
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14504 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14504 assert(sql_require_primary_key == 0 || sql_require_primary_key == 1);
4835
1/2
✓ Branch 0 taken 14504 times.
✗ Branch 1 not taken.
14504 if (!security_context.skip_priv_checks() &&
4836
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 17 times.
28 !security_context.has_access({SUPER_ACL}) &&
4837
5/6
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 14476 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 3 times.
14540 !security_context.has_access({"SYSTEM_VARIABLES_ADMIN"}) &&
4838
5/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 14503 times.
14512 !security_context.has_access({"SESSION_VARIABLES_ADMIN"})) {
4839
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report(
4840 ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4841
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4842 "SUPER, SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
4843 1 thd->is_slave_error = true;
4844 1 goto end;
4845 }
4846 14503 thd->variables.sql_require_primary_key = sql_require_primary_key;
4847 }
4848
4849
2/2
✓ Branch 0 taken 975 times.
✓ Branch 1 taken 555584 times.
556559 if (default_table_encryption != 0xff) {
4850
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 952 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
975 assert(default_table_encryption == 0 || default_table_encryption == 1);
4851 1950 if (thd->variables.default_table_encryption !=
4852 1001 static_cast<bool>(default_table_encryption) &&
4853
3/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 20 times.
26 !security_context.skip_priv_checks() &&
4854
4/6
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 949 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
1007 !security_context.has_access({SUPER_ACL}) &&
4855
5/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 972 times.
981 !security_context.has_access(
4856 {"SYSTEM_VARIABLES_ADMIN", "TABLE_ENCRYPTION_ADMIN"})) {
4857
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 rli->report(
4858 ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4859
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4860 "SUPER or SYSTEM_VARIABLES_ADMIN and TABLE_ENCRYPTION_ADMIN");
4861 3 thd->is_slave_error = true;
4862 3 goto end;
4863 }
4864 972 thd->variables.default_table_encryption = default_table_encryption;
4865 }
4866
4867 556556 thd->variables.binlog_ddl_skip_rewrite = (ddl_skip_rewrite != 0)? true : false;
4868
4869 556556 thd->table_map_for_update = (table_map)table_map_for_update;
4870
4871 556556 LEX_STRING user_lex = LEX_STRING();
4872 556556 LEX_STRING host_lex = LEX_STRING();
4873
2/2
✓ Branch 0 taken 4599 times.
✓ Branch 1 taken 551957 times.
556556 if (user) {
4874 4599 user_lex.str = const_cast<char *>(user);
4875 4599 user_lex.length = strlen(user);
4876 }
4877
2/2
✓ Branch 0 taken 4599 times.
✓ Branch 1 taken 551957 times.
556556 if (host) {
4878 4599 host_lex.str = const_cast<char *>(host);
4879 4599 host_lex.length = strlen(host);
4880 }
4881 556556 thd->set_invoker(&user_lex, &host_lex);
4882
4883 /*
4884 Flag if we need to rollback the statement transaction on
4885 slave if it by chance succeeds.
4886 If we expected a non-zero error code and get nothing and,
4887 it is a concurrency issue or ignorable issue, effects
4888 of the statement should be rolled back.
4889 */
4890
8/10
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 556174 times.
✓ Branch 2 taken 248 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 248 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 244 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 556418 times.
556658 if (expected_error && (ignored_error_code(expected_error) ||
4891 248 concurrency_error_code(expected_error))) {
4892 4 thd->variables.option_bits |= OPTION_MASTER_SQL_ERROR;
4893 }
4894
4895
1/2
✓ Branch 0 taken 556691 times.
✗ Branch 1 not taken.
556422 mysql_thread_set_secondary_engine(false);
4896
4897 /* Execute the query (note that we bypass dispatch_command()) */
4898
1/2
✓ Branch 0 taken 556815 times.
✗ Branch 1 not taken.
556691 Parser_state parser_state;
4899
4/8
✓ Branch 0 taken 556650 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 556865 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 556675 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 556710 times.
✗ Branch 7 not taken.
556815 if (!parser_state.init(thd, thd->query().str, thd->query().length)) {
4900 556710 parser_state.m_input.m_has_digest = true;
4901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556710 times.
556710 assert(thd->m_digest == nullptr);
4902 556710 thd->m_digest = &thd->m_digest_state;
4903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556710 times.
556710 assert(thd->m_statement_psi == nullptr);
4904
1/2
✓ Branch 0 taken 556644 times.
✗ Branch 1 not taken.
556710 thd->m_statement_psi = MYSQL_START_STATEMENT(
4905 &thd->m_statement_state, stmt_info_rpl.m_key, thd->db().str,
4906 thd->db().length, thd->charset(), nullptr);
4907
1/2
✓ Branch 0 taken 556819 times.
✗ Branch 1 not taken.
556644 THD_STAGE_INFO(thd, stage_starting);
4908
4909
1/2
✓ Branch 0 taken 556846 times.
✗ Branch 1 not taken.
556819 if (thd->m_digest != nullptr)
4910
1/2
✓ Branch 0 taken 556763 times.
✗ Branch 1 not taken.
556846 thd->m_digest->reset(thd->m_token_array, max_digest_length);
4911
4912 struct System_status_var query_start_status;
4913 556736 thd->clear_copy_status_var();
4914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 556368 times.
556368 if (opt_log_slow_extra) {
4915 thd->copy_status_var(&query_start_status);
4916 }
4917
4918
1/2
✓ Branch 0 taken 556450 times.
✗ Branch 1 not taken.
556368 dispatch_sql_command(thd, &parser_state, true);
4919
4920 556450 enum_sql_command command = thd->lex->sql_command;
4921
4922 /*
4923 Transaction isolation level of pure row based replicated transactions
4924 can be optimized to ISO_READ_COMMITTED by the applier when applying
4925 the Gtid_log_event.
4926
4927 If we are applying a statement other than transaction control ones
4928 after having optimized the transactions isolation level, we must warn
4929 about the non-standard situation we have found.
4930 */
4931
1/2
✓ Branch 0 taken 556094 times.
✗ Branch 1 not taken.
556450 if (is_sbr_logging_format() &&
4932
6/6
✓ Branch 0 taken 180563 times.
✓ Branch 1 taken 375531 times.
✓ Branch 2 taken 173174 times.
✓ Branch 3 taken 7389 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 556093 times.
729268 thd->variables.transaction_isolation > ISO_READ_COMMITTED &&
4933
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 173173 times.
173174 thd->tx_isolation == ISO_READ_COMMITTED) {
4934 1 String message;
4935
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 message.append(
4936 "The isolation level for the current transaction "
4937 "was changed to READ_COMMITTED based on the "
4938 "assumption that it had only row events and was "
4939 "not mixed with statements. "
4940 "However, an unexpected statement was found in "
4941 "the middle of the transaction."
4942 "Query: '");
4943
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 message.append(thd->query().str);
4944
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 message.append("'");
4945
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4946
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_SLAVE_FATAL_ERROR), message.c_ptr());
4947 1 thd->is_slave_error = true;
4948 1 goto end;
4949 1 }
4950
4951
7/8
✓ Branch 0 taken 555937 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 152706 times.
✓ Branch 3 taken 403231 times.
✓ Branch 4 taken 137932 times.
✓ Branch 5 taken 14768 times.
✓ Branch 6 taken 137945 times.
✓ Branch 7 taken 417986 times.
708793 if (sqlcom_can_generate_row_events(thd->lex->sql_command) &&
4952 152706 thd->get_row_count_func() > 0) {
4953
2/2
✓ Branch 0 taken 146217 times.
✓ Branch 1 taken 137823 times.
284040 for (TABLE_LIST *tbl = thd->lex->query_tables; tbl;
4954 146095 tbl = tbl->next_global) {
4955
5/6
✓ Branch 0 taken 146119 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 146121 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146123 times.
✓ Branch 5 taken 140 times.
146217 if (!tbl->is_placeholder() && tbl->table->file) {
4956
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 145955 times.
146123 if (!tbl->table->file->rpl_can_handle_stm_event()) {
4957 String message;
4958 message.append(
4959 "Masters binlog format is not ROW and storage "
4960 "engine can not handle non-ROW events at this "
4961 "time. Table: '");
4962 message.append(tbl->get_db_name());
4963 message.append(".");
4964 message.append(tbl->get_table_name());
4965 message.append("' Query: '");
4966 message.append(thd->query().str);
4967 message.append("'");
4968 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4969 ER_THD(thd, ER_SLAVE_FATAL_ERROR), message.c_ptr());
4970 thd->is_slave_error = true;
4971 goto end;
4972 }
4973 }
4974 }
4975 }
4976
4977 /*
4978 Do not need to increase rewrite_db_filter counter for
4979 SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_BEGIN and
4980 SQLCOM_COMMIT.
4981 */
4982
6/6
✓ Branch 0 taken 227 times.
✓ Branch 1 taken 555582 times.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 199 times.
✓ Branch 5 taken 15 times.
555809 if (need_inc_rewrite_db_filter_counter && command != SQLCOM_CREATE_DB &&
4983
4/4
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 125 times.
✓ Branch 3 taken 12 times.
199 command != SQLCOM_DROP_DB && command != SQLCOM_BEGIN &&
4984 command != SQLCOM_COMMIT) {
4985 125 Rpl_filter *rpl_filter = thd->rli_slave->rpl_filter;
4986
1/2
✓ Branch 0 taken 125 times.
✗ Branch 1 not taken.
125 if (rpl_filter)
4987 125 rpl_filter->get_rewrite_db_statistics()->increase_counter();
4988 }
4989 /* Finalize server status flags after executing a statement. */
4990
1/2
✓ Branch 0 taken 556286 times.
✗ Branch 1 not taken.
555809 thd->update_slow_query_status();
4991
1/2
✓ Branch 0 taken 556736 times.
✗ Branch 1 not taken.
556286 log_slow_statement(thd);
4992 }
4993
4994 556701 thd->variables.option_bits &= ~OPTION_MASTER_SQL_ERROR;
4995
4996 /*
4997 Resetting the enable_slow_log thd variable.
4998
4999 We need to reset it back to the opt_log_slow_replica_statements
5000 value after the statement execution (and slow logging
5001 is done). It might have changed if the statement was an
5002 admin statement (in which case, down in dispatch_sql_command execution
5003 thd->enable_slow_log is set to the value of
5004 opt_log_slow_admin_statements).
5005 */
5006 556701 thd->enable_slow_log = opt_log_slow_replica_statements;
5007
1/2
✓ Branch 0 taken 556164 times.
✗ Branch 1 not taken.
556702 } else {
5008 /*
5009 The query got a really bad error on the master (thread killed etc),
5010 which could be inconsistent. Parse it to test the table names: if the
5011 replicate-*-do|ignore-table rules say "this query must be ignored" then
5012 we exit gracefully; otherwise we warn about the bad error and tell DBA
5013 to check/fix it.
5014 */
5015 if (mysql_test_parse_for_slave(thd))
5016
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 clear_all_errors(
5017 thd, const_cast<Relay_log_info *>(rli)); /* Can ignore query */
5018 else {
5019 #ifdef WITH_WSREP
5020
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report(ERROR_LEVEL, ER_ERROR_ON_MASTER,
5021
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 ER_THD(thd, ER_ERROR_ON_MASTER), expected_error,
5022
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 (!opt_general_log_raw) && thd->rewritten_query().length()
5023
1/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 ? wsrep_thd_rewritten_query(thd).c_ptr_safe()
5024
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 : thd->query().str);
5025 #else
5026 rli->report(ERROR_LEVEL, ER_ERROR_ON_MASTER,
5027 ER_THD(thd, ER_ERROR_ON_MASTER), expected_error,
5028 thd->query().str);
5029 #endif /* WITH_WSREP */
5030 2 thd->is_slave_error = true;
5031 }
5032 5 goto end;
5033 }
5034 /* If the query was not ignored, it is printed to the general log */
5035
7/8
✓ Branch 0 taken 556439 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2261 times.
✓ Branch 3 taken 554178 times.
✓ Branch 4 taken 1785 times.
✓ Branch 5 taken 319 times.
✓ Branch 6 taken 272 times.
✓ Branch 7 taken 556010 times.
558268 if (!thd->is_error() ||
5036 2261 thd->get_stmt_da()->mysql_errno() != ER_SLAVE_IGNORED_TABLE) {
5037 /*
5038 Log the rewritten query if the query was rewritten
5039 and the option to log raw was not set.
5040
5041 There is an assumption here. We assume that query log
5042 events can never have multi-statement queries, thus the
5043 parsed statement is the same as the raw one.
5044 */
5045
6/8
✓ Branch 0 taken 556028 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 556066 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 554462 times.
✓ Branch 5 taken 1615 times.
✓ Branch 6 taken 554505 times.
✓ Branch 7 taken 1554 times.
556010 if (opt_general_log_raw || thd->rewritten_query().length() == 0)
5046
1/2
✓ Branch 0 taken 554829 times.
✗ Branch 1 not taken.
554530 query_logger.general_log_write(thd, COM_QUERY, thd->query().str,
5047
2/4
✓ Branch 0 taken 554541 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 554530 times.
✗ Branch 3 not taken.
554505 thd->query().length);
5048 else
5049
1/2
✓ Branch 0 taken 1701 times.
✗ Branch 1 not taken.
1701 query_logger.general_log_write(thd, COM_QUERY,
5050
1/2
✓ Branch 0 taken 1701 times.
✗ Branch 1 not taken.
1701 thd->rewritten_query().ptr(),
5051
1/2
✓ Branch 0 taken 1701 times.
✗ Branch 1 not taken.
1554 thd->rewritten_query().length());
5052 }
5053
5054 272 compare_errors:
5055 /* Parser errors shall be ignored when (GTID) skipping statements */
5056
3/4
✓ Branch 0 taken 556859 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2243 times.
559049 if (thd->is_error() &&
5057
4/4
✓ Branch 0 taken 2262 times.
✓ Branch 1 taken 554597 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 556841 times.
559105 thd->get_stmt_da()->mysql_errno() == ER_PARSE_ERROR &&
5058
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 gtid_pre_statement_checks(thd) == GTID_STATEMENT_SKIP) {
5059
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
2 thd->get_stmt_da()->reset_diagnostics_area();
5060 }
5061 /*
5062 In the slave thread, we may sometimes execute some DROP / * 40005
5063 TEMPORARY * / TABLE that come from parts of binlogs (likely if we
5064 use RESET SLAVE or CHANGE MASTER TO), while the temporary table
5065 has already been dropped. To ignore such irrelevant "table does
5066 not exist errors", we silently clear the error if TEMPORARY was used.
5067 */
5068 1126286 if (thd->lex->sql_command == SQLCOM_DROP_TABLE &&
5069
6/8
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 12008 times.
✓ Branch 2 taken 672 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 671 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
12681 thd->lex->drop_temporary && thd->is_error() &&
5070
5/6
✓ Branch 0 taken 12680 times.
✓ Branch 1 taken 544123 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 556802 times.
569484 thd->get_stmt_da()->mysql_errno() == ER_BAD_TABLE_ERROR &&
5071 !expected_error) {
5072
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->get_stmt_da()->reset_diagnostics_area();
5073 // Flag drops for error-ignored DDL to advance execution coordinates.
5074 1 has_ddl_committed = false;
5075 }
5076 /*
5077 If we expected a non-zero error code, and we don't get the same error
5078 code, and it should be ignored or is related to a concurrency issue.
5079 */
5080
3/4
✓ Branch 0 taken 556816 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2259 times.
✓ Branch 3 taken 554557 times.
556803 actual_error = thd->is_error() ? thd->get_stmt_da()->mysql_errno() : 0;
5081
3/8
✓ Branch 0 taken 556810 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 556825 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 556825 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
556816 DBUG_PRINT("info", ("expected_error: %d sql_errno: %d", expected_error,
5082 actual_error));
5083
5084
4/4
✓ Branch 0 taken 2259 times.
✓ Branch 1 taken 554495 times.
✓ Branch 2 taken 232 times.
✓ Branch 3 taken 2027 times.
556754 if (actual_error != 0 && expected_error == actual_error) {
5085 696 if (!has_ddl_committed && // Slave didn't commit a DDL
5086
1/2
✓ Branch 0 taken 232 times.
✗ Branch 1 not taken.
232 ddl_xid == binary_log::INVALID_XID && // The event was not logged as
5087 // atomic DDL on master
5088
4/6
✓ Branch 0 taken 232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 232 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 228 times.
696 !thd->rli_slave->ddl_not_atomic && // The DDL was considered atomic
5089 // by the slave
5090
3/4
✓ Branch 0 taken 232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 228 times.
232 is_atomic_ddl(thd, true)) // The DDL is atomic for the local server
5091 {
5092
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 thd->get_stmt_da()->reset_diagnostics_area();
5093
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_SLAVE_POSSIBLY_DIVERGED_AFTER_DDL, MYF(0), 0);
5094 4 actual_error = ER_SLAVE_POSSIBLY_DIVERGED_AFTER_DDL;
5095 }
5096 }
5097
5098 /*
5099 If a statement with expected error is received on slave and if the
5100 statement is not filtered on the slave, only then compare the expected
5101 error with the actual error that happened on slave.
5102 */
5103
5/6
✓ Branch 0 taken 248 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 246 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 228 times.
248 if ((expected_error && rli->rpl_filter->db_ok(thd->db().str) &&
5104 18 expected_error != actual_error &&
5105
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 !concurrency_error_code(expected_error)) &&
5106
7/8
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 556506 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 556742 times.
557014 !ignored_error_code(actual_error) &&
5107
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 !ignored_error_code(expected_error)) {
5108
3/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 3 times.
12 if (!ignored_error_code(ER_INCONSISTENT_ERROR)) {
5109
4/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
18 rli->report(
5110 ERROR_LEVEL, ER_INCONSISTENT_ERROR,
5111
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 ER_THD(thd, ER_INCONSISTENT_ERROR),
5112
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 ER_THD_NONCONST(thd, expected_error), expected_error,
5113 2 (actual_error ? thd->get_stmt_da()->message_text() : "no error"),
5114 #ifdef WITH_WSREP
5115 actual_error, print_slave_db_safe(db),
5116
3/6
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
9 ((!opt_general_log_raw) && thd->rewritten_query().length()
5117
1/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9 ? wsrep_thd_rewritten_query(thd).c_ptr_safe()
5118 : query_arg));
5119 #else
5120 actual_error, print_slave_db_safe(db), query_arg);
5121 #endif /* WITH_WSREP */
5122 9 thd->is_slave_error = true;
5123 } else {
5124
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 rli->report(
5125 INFORMATION_LEVEL, actual_error,
5126 "The actual error and expected error on slave are"
5127 " different that will result in ER_INCONSISTENT_ERROR but"
5128 " that is passed as an argument to replica_skip_errors so no"
5129 " error is thrown. "
5130 "The expected error was %s with, Error_code: %d. "
5131 "The actual error is %s with ",
5132
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ER_THD_NONCONST(thd, expected_error), expected_error,
5133 3 thd->get_stmt_da()->message_text());
5134
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
5135 }
5136 }
5137 /*
5138 If we get the same error code as expected and it is not a concurrency
5139 issue, or should be ignored.
5140 */
5141 1111435 else if ((expected_error == actual_error &&
5142
6/6
✓ Branch 0 taken 554693 times.
✓ Branch 1 taken 2049 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 554700 times.
✓ Branch 4 taken 555061 times.
✓ Branch 5 taken 1672 times.
558775 !concurrency_error_code(expected_error)) ||
5143
3/4
✓ Branch 0 taken 2033 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 346 times.
✓ Branch 3 taken 1687 times.
2051 ignored_error_code(actual_error)) {
5144
3/8
✓ Branch 0 taken 555121 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 555122 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 555122 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
555061 DBUG_PRINT("info", ("error ignored"));
5145
7/8
✓ Branch 0 taken 574 times.
✓ Branch 1 taken 554526 times.
✓ Branch 2 taken 574 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 346 times.
✓ Branch 5 taken 228 times.
✓ Branch 6 taken 346 times.
✓ Branch 7 taken 554754 times.
555100 if (actual_error && ignored_error_code(actual_error)) {
5146
2/2
✓ Branch 0 taken 319 times.
✓ Branch 1 taken 27 times.
346 if (actual_error == ER_SLAVE_IGNORED_TABLE) {
5147
3/4
✓ Branch 0 taken 319 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 254 times.
319 if (!slave_ignored_err_throttle.log())
5148
2/4
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
65 rli->report(INFORMATION_LEVEL, actual_error,
5149 "Could not execute %s event. Detailed error: %s;"
5150 " Error log throttle is enabled. This error will not be"
5151 " displayed for next %lu secs. It will be suppressed",
5152 65 get_type_str(), thd->get_stmt_da()->message_text(),
5153 (window_size / 1000000));
5154 } else
5155
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 rli->report(INFORMATION_LEVEL, actual_error,
5156 "Could not execute %s event. Detailed error: %s;",
5157 27 get_type_str(), thd->get_stmt_da()->message_text());
5158 }
5159 555100 has_ddl_committed = false; // The same comments as above.
5160
1/2
✓ Branch 0 taken 555149 times.
✗ Branch 1 not taken.
555100 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
5161 555149 thd->killed = THD::NOT_KILLED;
5162 }
5163 /*
5164 Other cases: mostly we expected no error and get one.
5165 */
5166
4/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1666 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1681 times.
✗ Branch 5 not taken.
1672 else if (thd->is_slave_error || thd->is_fatal_error()) {
5167
2/4
✓ Branch 0 taken 1681 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1681 times.
✗ Branch 3 not taken.
1681 if (!is_silent_error(thd)) {
5168
3/6
✓ Branch 0 taken 1681 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1681 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1681 times.
✗ Branch 5 not taken.
3362 rli->report(ERROR_LEVEL, actual_error,
5169 "Error '%s' on query. Default database: '%s'. Query: '%s'",
5170 1681 (actual_error ? thd->get_stmt_da()->message_text()
5171 : "unexpected success or fatal error"),
5172 #ifdef WITH_WSREP
5173 print_slave_db_safe(db),
5174
4/6
✓ Branch 0 taken 1681 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1681 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1675 times.
1681 ((!opt_general_log_raw) && thd->rewritten_query().length()
5175
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 1675 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1687 ? wsrep_thd_rewritten_query(thd).c_ptr_safe()
5176 : query_arg));
5177 #else
5178 print_slave_db_safe(thd->db().str), query_arg);
5179 #endif /* WITH_WSREP */
5180 }
5181 1681 thd->is_slave_error = true;
5182
5183 #ifdef WITH_WSREP
5184 /* If DDL evaluate if user has configured to ignore certain errors. */
5185
8/10
✓ Branch 0 taken 1681 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1386 times.
✓ Branch 3 taken 295 times.
✓ Branch 4 taken 1386 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 1380 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 1675 times.
1681 if (wsrep_thd_is_toi(thd) && wsrep_must_ignore_error(thd)) {
5186
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 thd->clear_error();
5187 6 thd->killed = THD::NOT_KILLED;
5188 6 thd->wsrep_has_ignored_error = true;
5189 }
5190 #endif /* WITH_WSREP */
5191 }
5192
5193 /*
5194 TODO: compare the values of "affected rows" around here. Something
5195 like:
5196 if ((uint32) affected_in_event != (uint32) affected_on_slave)
5197 {
5198 sql_print_error("Slave: did not get the expected number of affected "
5199 "rows running query from master - expected %d, got %d (this numbers "
5200 "should have matched modulo 4294967296).", 0, ...);
5201 thd->is_slave_error = 1;
5202 }
5203 We may also want an option to tell the slave to ignore "affected"
5204 mismatch. This mismatch could be implemented with a new ER_ code, and
5205 to ignore it you would use --replica-skip-errors...
5206
5207 To do the comparison we need to know the value of "affected" which the
5208 above dispatch_sql_command() computed. And we need to know the value of
5209 "affected" in the master's binlog. Both will be implemented later. The
5210 important thing is that we now have the format ready to log the values
5211 of "affected" in the binlog. So we can release 5.0.0 before effectively
5212 logging "affected" and effectively comparing it.
5213 */
5214
2/2
✓ Branch 0 taken 556836 times.
✓ Branch 1 taken 21 times.
556784 } /* End of if (db_ok(... */
5215
5216 {
5217 /**
5218 The following failure injection works in cooperation with tests
5219 setting @@global.debug= 'd,stop_replica_middle_group'.
5220 The sql thread receives the killed status and will proceed
5221 to shutdown trying to finish incomplete events group.
5222 */
5223
5224 // TODO: address the middle-group killing in MTS case
5225
5226
9/12
✓ Branch 0 taken 556783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 556775 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
556836 DBUG_EXECUTE_IF("stop_replica_middle_group", {
5227 if (strcmp("COMMIT", query) != 0 && strcmp("BEGIN", query) != 0) {
5228 if (thd->get_transaction()->cannot_safely_rollback(
5229 Transaction_ctx::SESSION)) {
5230 auto thd_rli = (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL
5231 ? const_cast<Relay_log_info *>(rli)
5232 : static_cast<Slave_worker *>(
5233 const_cast<Relay_log_info *>(rli))
5234 ->c_rli);
5235 thd_rli->abort_slave = 1;
5236 }
5237 }
5238 };);
5239 }
5240
5241 556775 end:
5242
5243
3/4
✓ Branch 0 taken 3214 times.
✓ Branch 1 taken 553590 times.
✓ Branch 2 taken 3214 times.
✗ Branch 3 not taken.
556804 if (thd->temporary_tables) detach_temp_tables_worker(thd, rli);
5244 /*
5245 Probably we have set thd->query, thd->db, thd->catalog to point to places
5246 in the data_buf of this event. Now the event is going to be deleted
5247 probably, so data_buf will be freed, so the thd->... listed above will be
5248 pointers to freed memory.
5249 So we must set them to 0, so that those bad pointers values are not later
5250 used. Note that "cleanup" queries like automatic DROP TEMPORARY TABLE
5251 don't suffer from these assignments to 0 as DROP TEMPORARY
5252 TABLE uses the db.table syntax.
5253 */
5254 556804 thd->set_catalog(NULL_CSTR);
5255
1/2
✓ Branch 0 taken 556872 times.
✗ Branch 1 not taken.
556748 thd->set_db(NULL_CSTR); /* will free the current database */
5256
1/2
✓ Branch 0 taken 556893 times.
✗ Branch 1 not taken.
556872 thd->reset_query();
5257 556893 thd->lex->sql_command = SQLCOM_END;
5258
3/8
✓ Branch 0 taken 556867 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 556864 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 556864 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
556893 DBUG_PRINT("info", ("end: query= 0"));
5259
5260 /* Mark the statement completed. */
5261
1/2
✓ Branch 0 taken 556698 times.
✗ Branch 1 not taken.
556864 MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
5262
5263 /* Maintain compatibility with the legacy processlist. */
5264
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 556698 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
556698 if (pfs_processlist_enabled) thd->reset_query_for_display();
5265
5266
1/2
✓ Branch 0 taken 556775 times.
✗ Branch 1 not taken.
556698 thd->reset_rewritten_query();
5267 556775 thd->m_statement_psi = nullptr;
5268 556775 thd->m_digest = nullptr;
5269
5270 /*
5271 Prevent rewritten query from getting "stuck" in SHOW PROCESSLIST,
5272 and performance_schema.threads.
5273 */
5274
1/2
✓ Branch 0 taken 556823 times.
✗ Branch 1 not taken.
556775 thd->reset_rewritten_query();
5275
1/2
✓ Branch 0 taken 556884 times.
✗ Branch 1 not taken.
556823 thd->reset_query_for_display();
5276
5277 /*
5278 As a disk space optimization, future masters will not log an event for
5279 LAST_INSERT_ID() if that function returned 0 (and thus they will be able
5280 to replace the THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
5281 variable by (THD->first_successful_insert_id_in_prev_stmt > 0) ; with the
5282 resetting below we are ready to support that.
5283 */
5284 556884 thd->first_successful_insert_id_in_prev_stmt_for_binlog = 0;
5285 556884 thd->first_successful_insert_id_in_prev_stmt = 0;
5286 556884 thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt = false;
5287
1/2
✓ Branch 0 taken 556887 times.
✗ Branch 1 not taken.
556884 thd->mem_root->ClearForReuse();
5288 556866 return thd->is_slave_error;
5289 556887 }
5290
5291 1916 int Query_log_event::do_update_pos(Relay_log_info *rli) {
5292 1916 int ret = Log_event::do_update_pos(rli);
5293
5294
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1916 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1916 DBUG_EXECUTE_IF(
5295 "crash_after_commit_and_update_pos", if (!strcmp("COMMIT", query)) {
5296 sql_print_information("Crashing crash_after_commit_and_update_pos.");
5297 rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
5298 ha_flush_logs(0);
5299 DBUG_SUICIDE();
5300 });
5301
5302 1916 return ret;
5303 }
5304
5305 523927 Log_event::enum_skip_reason Query_log_event::do_shall_skip(
5306 Relay_log_info *rli) {
5307
1/2
✓ Branch 0 taken 523927 times.
✗ Branch 1 not taken.
523927 DBUG_TRACE;
5308
3/8
✓ Branch 0 taken 523926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 523926 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 523926 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
523927 DBUG_PRINT("debug", ("query: %s; q_len: %d", query, static_cast<int>(q_len)));
5309
2/4
✓ Branch 0 taken 523926 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 523926 times.
✗ Branch 3 not taken.
523926 assert(query && q_len > 0);
5310
5311
2/2
✓ Branch 0 taken 399 times.
✓ Branch 1 taken 523527 times.
523926 if (rli->slave_skip_counter > 0) {
5312
2/2
✓ Branch 0 taken 305 times.
✓ Branch 1 taken 94 times.
399 if (strcmp("BEGIN", query) == 0) {
5313 305 thd->variables.option_bits |= OPTION_BEGIN;
5314
1/2
✓ Branch 0 taken 305 times.
✗ Branch 1 not taken.
305 return Log_event::continue_group(rli);
5315 }
5316
5317
3/4
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 67 times.
94 if (strcmp("COMMIT", query) == 0 || strcmp("ROLLBACK", query) == 0) {
5318 27 thd->variables.option_bits &= ~OPTION_BEGIN;
5319 27 return Log_event::EVENT_SKIP_COUNT;
5320 }
5321 }
5322
1/2
✓ Branch 0 taken 523594 times.
✗ Branch 1 not taken.
523594 Log_event::enum_skip_reason ret = Log_event::do_shall_skip(rli);
5323 523594 return ret;
5324 523926 }
5325
5326 #endif
5327
5328 /**
5329 Return the query string pointer (and its size) from a Query log event
5330 using only the event buffer (we don't instantiate a Query_log_event
5331 object for this).
5332
5333 @param buf Pointer to the event buffer.
5334 @param length The size of the event buffer.
5335 @param fd_event The description event of the master which logged
5336 the event.
5337 @param[out] query_arg The pointer to receive the query pointer.
5338
5339 @return The size of the query.
5340 */
5341 528930 size_t Query_log_event::get_query(const char *buf, size_t length,
5342 const Format_description_event *fd_event,
5343 const char **query_arg) {
5344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 528930 times.
528930 assert((Log_event_type)buf[EVENT_TYPE_OFFSET] == binary_log::QUERY_EVENT);
5345
5346 char db_len; /* size of db name */
5347 528930 uint status_vars_len = 0; /* size of status_vars */
5348 size_t qlen; /* size of the query */
5349 528930 int checksum_size = 0; /* size of trailing checksum */
5350 const char *end_of_query;
5351
5352 528930 uint common_header_len = fd_event->common_header_len;
5353 uint query_header_len =
5354 528930 fd_event->post_header_len[binary_log::QUERY_EVENT - 1];
5355
5356 /* Error if the event content is too small */
5357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 528930 times.
528930 if (length < (common_header_len + query_header_len)) goto err;
5358
5359 /* Skip the header */
5360 528930 buf += common_header_len;
5361
5362 /* Check if there are status variables in the event */
5363
1/2
✓ Branch 0 taken 528930 times.
✗ Branch 1 not taken.
528930 if ((query_header_len - QUERY_HEADER_MINIMAL_LEN) > 0) {
5364 528930 status_vars_len = uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
5365 }
5366
5367 /* Check if the event has trailing checksum */
5368
2/2
✓ Branch 0 taken 505618 times.
✓ Branch 1 taken 23312 times.
528930 if (fd_event->footer()->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF)
5369 505618 checksum_size = 4;
5370
5371 528930 db_len = (uchar)buf[Q_DB_LEN_OFFSET];
5372
5373 /* Error if the event content is too small */
5374 528930 if (length < (common_header_len + query_header_len + db_len + 1 +
5375
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 528930 times.
528930 status_vars_len + checksum_size))
5376 goto err;
5377
5378 528930 *query_arg = buf + query_header_len + db_len + 1 + status_vars_len;
5379
5380 /* Calculate the query length */
5381 528930 end_of_query = buf +
5382 528930 (length - common_header_len) - /* we skipped the header */
5383 528930 checksum_size;
5384 528930 qlen = end_of_query - *query_arg;
5385 528930 return qlen;
5386
5387 err:
5388 *query_arg = nullptr;
5389 return 0;
5390 }
5391
5392 /***************************************************************************
5393 Format_description_log_event methods
5394 ****************************************************************************/
5395
5396 /**
5397 Format_description_log_event 1st ctor.
5398
5399 Ctor. Can be used to create the event to write to the binary log (when the
5400 server starts or when FLUSH LOGS).
5401 */
5402 163399 Format_description_log_event::Format_description_log_event()
5403 : Format_description_event(BINLOG_VERSION, ::server_version),
5404 #ifdef MYSQL_SERVER
5405 Log_event(header(), footer(), Log_event::EVENT_INVALID_CACHE,
5406
1/2
✓ Branch 0 taken 163377 times.
✗ Branch 1 not taken.
163399 Log_event::EVENT_INVALID_LOGGING)
5407 #else
5408 Log_event(header(), footer())
5409 #endif
5410 {
5411 163379 common_header->set_is_valid(true);
5412 163380 }
5413
5414 /**
5415 The problem with this constructor is that the fixed header may have a
5416 length different from this version, but we don't know this length as we
5417 have not read the Format_description_log_event which says it, yet. This
5418 length is in the post-header of the event, but we don't know where the
5419 post-header starts.
5420
5421 So this type of event HAS to:
5422 - either have the header's length at the beginning (in the header, at a
5423 fixed position which will never be changed), not in the post-header. That
5424 would make the header be "shifted" compared to other events.
5425 - or have a header of size LOG_EVENT_MINIMAL_HEADER_LEN (19), in all future
5426 versions, so that we know for sure.
5427
5428 I (Guilhem) chose the 2nd solution. Rotate has the same constraint (because
5429 it is sent before Format_description_log_event).
5430 */
5431
5432 161794 Format_description_log_event::Format_description_log_event(
5433 161794 const char *buf, const Format_description_event *description_event)
5434 : Format_description_event(buf, description_event),
5435
1/2
✓ Branch 0 taken 156738 times.
✗ Branch 1 not taken.
161794 Log_event(header(), footer()) {
5436
1/2
✓ Branch 0 taken 161793 times.
✗ Branch 1 not taken.
161773 DBUG_TRACE;
5437
3/4
✓ Branch 0 taken 156752 times.
✓ Branch 1 taken 5031 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 156752 times.
161793 if (!is_valid()) return;
5438 161783 common_header->type_code = binary_log::FORMAT_DESCRIPTION_EVENT;
5439
2/2
✓ Branch 0 taken 161790 times.
✓ Branch 1 taken 2 times.
161783 }
5440
5441 #ifndef MYSQL_SERVER
5442 5005 void Format_description_log_event::print(
5443 FILE *, PRINT_EVENT_INFO *print_event_info) const {
5444
1/2
✓ Branch 0 taken 5005 times.
✗ Branch 1 not taken.
5005 DBUG_TRACE;
5445
5446 5005 IO_CACHE *const head = &print_event_info->head_cache;
5447
5448
2/2
✓ Branch 0 taken 4747 times.
✓ Branch 1 taken 258 times.
5005 if (!print_event_info->short_form) {
5449
1/2
✓ Branch 0 taken 4747 times.
✗ Branch 1 not taken.
4747 print_header(head, print_event_info, false);
5450 4747 my_b_printf(head, "\tStart: binlog v %d, server v %s created ",
5451
1/2
✓ Branch 0 taken 4747 times.
✗ Branch 1 not taken.
4747 binlog_version, server_version);
5452
1/2
✓ Branch 0 taken 4747 times.
✗ Branch 1 not taken.
4747 print_timestamp(head, nullptr);
5453
3/4
✓ Branch 0 taken 3752 times.
✓ Branch 1 taken 995 times.
✓ Branch 2 taken 3752 times.
✗ Branch 3 not taken.
4747 if (created) my_b_printf(head, " at startup");
5454
1/2
✓ Branch 0 taken 4747 times.
✗ Branch 1 not taken.
4747 my_b_printf(head, "\n");
5455
2/2
✓ Branch 0 taken 3722 times.
✓ Branch 1 taken 1025 times.
4747 if (common_header->flags & LOG_EVENT_BINLOG_IN_USE_F)
5456
1/2
✓ Branch 0 taken 3722 times.
✗ Branch 1 not taken.
3722 my_b_printf(head,
5457 "# Warning: this binlog is either in use or was not "
5458 "closed properly.\n");
5459 }
5460
5461
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 4972 times.
5005 if (is_relay_log_event()) {
5462
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 my_b_printf(head,
5463 "# This Format_description_event appears in a relay log "
5464 "and was generated by the slave thread.\n");
5465 33 return;
5466 }
5467
5468
6/6
✓ Branch 0 taken 4958 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 3884 times.
✓ Branch 3 taken 1074 times.
✓ Branch 4 taken 3884 times.
✓ Branch 5 taken 1088 times.
4972 if (!is_artificial_event() && created) {
5469 #ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND
5470 /*
5471 This is for mysqlbinlog: like in replication, we want to delete the stale
5472 tmp files left by an unclean shutdown of mysqld (temporary tables)
5473 and rollback unfinished transaction.
5474 Probably this can be done with RESET CONNECTION (syntax to be defined).
5475 */
5476 my_b_printf(head, "RESET CONNECTION%s\n", print_event_info->delimiter);
5477 #else
5478
1/2
✓ Branch 0 taken 3884 times.
✗ Branch 1 not taken.
3884 my_b_printf(head, "ROLLBACK%s\n", print_event_info->delimiter);
5479 #endif
5480 }
5481
3/4
✓ Branch 0 taken 4972 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4943 times.
✓ Branch 3 taken 29 times.
4972 if (temp_buf && print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
5482
2/2
✓ Branch 0 taken 4709 times.
✓ Branch 1 taken 234 times.
4943 !print_event_info->short_form) {
5483
2/2
✓ Branch 0 taken 4666 times.
✓ Branch 1 taken 43 times.
4709 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
5484
1/2
✓ Branch 0 taken 4666 times.
✗ Branch 1 not taken.
4666 my_b_printf(head, "BINLOG '\n");
5485
1/2
✓ Branch 0 taken 4709 times.
✗ Branch 1 not taken.
4709 print_base64(head, print_event_info, false);
5486 4709 print_event_info->printed_fd_event = true;
5487
5488 /*
5489 If --skip-gtids is given, the server when it replays the output
5490 should generate a new GTID if gtid_mode=ON. However, when the
5491 server reads the base64-encoded Format_description_log_event, it
5492 will cleverly detect that this is a binlog to be replayed, and
5493 act a little bit like the replication thread, in the following
5494 sense: if the thread does not see any 'SET GTID_NEXT' statement,
5495 it will assume the binlog was created by an old server and try
5496 to preserve transactions as anonymous. This is the opposite of
5497 what we want when passing the --skip-gtids flag, so therefore we
5498 output the following statement.
5499
5500 The behavior where the client preserves transactions following a
5501 Format_description_log_event as anonymous was introduced in
5502 5.6.16.
5503 */
5504
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4706 times.
4709 if (print_event_info->skip_gtids)
5505 3 my_b_printf(head, "/*!50616 SET @@SESSION.GTID_NEXT='AUTOMATIC'*/%s\n",
5506
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 print_event_info->delimiter);
5507 }
5508
2/2
✓ Branch 0 taken 4972 times.
✓ Branch 1 taken 33 times.
5005 }
5509 #endif /* !MYSQL_SERVER */
5510
5511 #ifdef MYSQL_SERVER
5512 4703 int Format_description_log_event::pack_info(Protocol *protocol) {
5513 char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
5514 4703 pos = my_stpcpy(buf, "Server ver: ");
5515 4703 pos = my_stpcpy(pos, server_version);
5516 4703 pos = my_stpcpy(pos, ", Binlog ver: ");
5517
1/2
✓ Branch 0 taken 4703 times.
✗ Branch 1 not taken.
4703 pos = longlong10_to_str(binlog_version, pos, 10);
5518
1/2
✓ Branch 0 taken 4703 times.
✗ Branch 1 not taken.
4703 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
5519 4703 return 0;
5520 }
5521
5522 85882 bool Format_description_log_event::write(Basic_ostream *ostream) {
5523 bool ret;
5524 bool no_checksum;
5525 uchar buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN +
5526 BINLOG_CHECKSUM_ALG_DESC_LEN];
5527 85882 size_t rec_size = sizeof(buff);
5528 85882 int2store(buff + ST_BINLOG_VER_OFFSET, binlog_version);
5529 85882 memcpy((char *)buff + ST_SERVER_VER_OFFSET, server_version,
5530 ST_SERVER_VER_LEN);
5531
3/4
✓ Branch 0 taken 41762 times.
✓ Branch 1 taken 44120 times.
✓ Branch 2 taken 41762 times.
✗ Branch 3 not taken.
85882 if (!dont_set_created) created = get_time();
5532 85882 int4store(buff + ST_CREATED_OFFSET, static_cast<uint32>(created));
5533 85882 buff[ST_COMMON_HEADER_LEN_OFFSET] = LOG_EVENT_HEADER_LEN;
5534
5535 85882 size_t number_of_events = 0;
5536 85882 int post_header_len_size = static_cast<int>(post_header_len.size());
5537
5538
1/2
✓ Branch 0 taken 85882 times.
✗ Branch 1 not taken.
85882 if (post_header_len_size == Binary_log_event::LOG_EVENT_TYPES)
5539 // Replicating between master and slave with same version.
5540 // number_of_events will be same as Binary_log_event::LOG_EVENT_TYPES
5541 85882 number_of_events = Binary_log_event::LOG_EVENT_TYPES;
5542 else if (post_header_len_size > Binary_log_event::LOG_EVENT_TYPES)
5543 /*
5544 Replicating between new master and old slave.
5545 In that case there won't be any memory issues, as there won't be
5546 any out of memory read.
5547 */
5548 number_of_events = Binary_log_event::LOG_EVENT_TYPES;
5549 else
5550 /*
5551 Replicating between old master and new slave.
5552 In that case it might lead to different number_of_events on master and
5553 slave. When the relay log is rotated, the FDE from master is used to
5554 create the FDE event on slave, which is being written here. In that case
5555 we might end up reading more bytes as
5556 post_header_len.size() < Binary_log_event::LOG_EVENT_TYPES;
5557 causing memory issues.
5558 */
5559 number_of_events = post_header_len_size;
5560
5561 85882 memcpy((char *)buff + ST_COMMON_HEADER_LEN_OFFSET + 1,
5562 85882 &post_header_len.front(), number_of_events);
5563 /*
5564 if checksum is requested
5565 record the checksum-algorithm descriptor next to
5566 post_header_len vector which will be followed by the checksum value.
5567 Master is supposed to trigger checksum computing by binlog_checksum_options,
5568 slave does it via marking the event according to
5569 FD_queue checksum_alg value.
5570 */
5571 static_assert(BINLOG_CHECKSUM_ALG_DESC_LEN == 1, "");
5572 #ifndef NDEBUG
5573 85882 common_header->data_written = 0; // to prepare for need_checksum assert
5574 #endif
5575 85882 buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN] =
5576
3/4
✓ Branch 0 taken 85882 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 73273 times.
✓ Branch 3 taken 12609 times.
85882 need_checksum() ? (uint8)common_footer->checksum_alg
5577 : (uint8)binary_log::BINLOG_CHECKSUM_ALG_OFF;
5578 /*
5579 FD of checksum-aware server is always checksum-equipped, (V) is in,
5580 regardless of @@global.binlog_checksum policy.
5581 Thereby a combination of (A) == 0, (V) != 0 means
5582 it's the checksum-aware server's FD event that heads checksum-free binlog
5583 file.
5584 Here 0 stands for checksumming OFF to evaluate (V) as 0 is that case.
5585 A combination of (A) != 0, (V) != 0 denotes FD of the checksum-aware server
5586 heading the checksummed binlog.
5587 (A), (V) presence in FD of the checksum-aware server makes the event
5588 1 + 4 bytes bigger comparing to the former FD.
5589 */
5590
5591
2/2
✓ Branch 0 taken 12609 times.
✓ Branch 1 taken 73273 times.
85882 if ((no_checksum = (common_footer->checksum_alg ==
5592 binary_log::BINLOG_CHECKSUM_ALG_OFF))) {
5593 // Forcing (V) room to fill anyway
5594 12609 common_footer->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_CRC32;
5595 }
5596
1/2
✓ Branch 0 taken 85882 times.
✗ Branch 1 not taken.
85882 ret = (write_header(ostream, rec_size) ||
5597
3/6
✓ Branch 0 taken 85882 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85882 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 85882 times.
✗ Branch 5 not taken.
171764 wrapper_my_b_safe_write(ostream, buff, rec_size) ||
5598
2/4
✓ Branch 0 taken 85882 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 85882 times.
85882 write_footer(ostream));
5599
2/2
✓ Branch 0 taken 12609 times.
✓ Branch 1 taken 73273 times.
85882 if (no_checksum)
5600 12609 common_footer->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_OFF;
5601 85882 return ret;
5602 }
5603
5604 48906 int Format_description_log_event::do_apply_event(Relay_log_info const *rli) {
5605 48906 int ret = 0;
5606
1/2
✓ Branch 0 taken 48906 times.
✗ Branch 1 not taken.
48906 DBUG_TRACE;
5607
5608 /*
5609 As a transaction NEVER spans on 2 or more binlogs:
5610 if we have an active transaction at this point, the master died
5611 while writing the transaction to the binary log, i.e. while
5612 flushing the binlog cache to the binlog. XA guarantees that master has
5613 rolled back. So we roll back.
5614 Note: this event could be sent by the master to inform us of the
5615 format of its binlog; in other words maybe it is not at its
5616 original place when it comes to us; we'll know this by checking
5617 log_pos ("artificial" events have log_pos == 0).
5618 */
5619
8/10
✓ Branch 0 taken 47942 times.
✓ Branch 1 taken 964 times.
✓ Branch 2 taken 43586 times.
✓ Branch 3 taken 4356 times.
✓ Branch 4 taken 10887 times.
✓ Branch 5 taken 32699 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10887 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 48906 times.
59793 if (!thd->rli_fake && !is_artificial_event() && created &&
5620 10887 thd->get_transaction()->is_active(Transaction_ctx::SESSION)) {
5621 /* This is not an error (XA is safe), just an information */
5622 rli->report(INFORMATION_LEVEL, 0,
5623 "Rolling back unfinished transaction (no COMMIT "
5624 "or ROLLBACK in relay log). A probable cause is that "
5625 "the master died while writing the transaction to "
5626 "its binary log, thus rolled back too.");
5627 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, true);
5628 }
5629
5630 /* If this event comes from ourself, there is no cleaning task to perform. */
5631
2/2
✓ Branch 0 taken 13810 times.
✓ Branch 1 taken 35096 times.
48906 if (server_id != (uint32)::server_id) {
5632
4/4
✓ Branch 0 taken 4553 times.
✓ Branch 1 taken 9257 times.
✓ Branch 2 taken 3671 times.
✓ Branch 3 taken 882 times.
13810 if (created && !thd->variables.require_row_format) {
5633
1/2
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
3671 ret = close_temporary_tables(thd);
5634
1/2
✓ Branch 0 taken 3671 times.
✗ Branch 1 not taken.
3671 cleanup_load_tmpdir();
5635 } else {
5636 /*
5637 Set all temporary tables thread references to the current thread
5638 as they may point to the "old" SQL slave thread in case of its
5639 restart.
5640 */
5641 TABLE *table;
5642
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 10139 times.
10236 for (table = thd->temporary_tables; table; table = table->next)
5643 97 table->in_use = thd;
5644 }
5645 }
5646
5647
1/2
✓ Branch 0 taken 48906 times.
✗ Branch 1 not taken.
48906 if (!ret) {
5648 /* Save the information describing this binlog */
5649
1/2
✓ Branch 0 taken 48906 times.
✗ Branch 1 not taken.
48906 ret = const_cast<Relay_log_info *>(rli)->set_rli_description_event(this);
5650 }
5651
5652 48906 return ret;
5653 48906 }
5654
5655 47942 int Format_description_log_event::do_update_pos(Relay_log_info *rli) {
5656
2/2
✓ Branch 0 taken 34941 times.
✓ Branch 1 taken 13001 times.
47942 if (server_id == (uint32)::server_id) {
5657 /*
5658 We only increase the relay log position if we are skipping
5659 events and do not touch any group_* variables, nor flush the
5660 relay log info. If there is a crash, we will have to re-skip
5661 the events again, but that is a minor issue.
5662
5663 If we do not skip stepping the group log position (and the
5664 server id was changed when restarting the server), it might well
5665 be that we start executing at a position that is invalid, e.g.,
5666 at a Rows_log_event or a Query_log_event preceded by a
5667 Intvar_log_event instead of starting at a Table_map_log_event or
5668 the Intvar_log_event respectively.
5669 */
5670 34941 rli->inc_event_relay_log_pos();
5671 34941 return 0;
5672 } else {
5673 13001 return Log_event::do_update_pos(rli);
5674 }
5675 }
5676
5677 47918 Log_event::enum_skip_reason Format_description_log_event::do_shall_skip(
5678 Relay_log_info *) {
5679 47918 return Log_event::EVENT_SKIP_NOT;
5680 }
5681
5682 #endif /* MYSQL_SERVER */
5683
5684 29 Start_encryption_log_event::Start_encryption_log_event(
5685 29 const char *buf, const Format_description_event *description_event)
5686 : Start_encryption_event(buf, description_event),
5687
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
29 Log_event(header(), footer()) {}
5688
5689 #ifdef MYSQL_SERVER
5690 2 int Start_encryption_log_event::do_update_pos(Relay_log_info *rli) {
5691 /*
5692 Master never sends Start_encryption_log_event, any SELE that a slave
5693 might see was created locally in MYSQL_BIN_LOG::open() on the slave
5694 */
5695 2 rli->inc_event_relay_log_pos();
5696 2 return 0;
5697 }
5698
5699 #endif
5700
5701 #ifndef MYSQL_SERVER
5702 6 void Start_encryption_log_event::print(
5703 FILE *file [[maybe_unused]],
5704 PRINT_EVENT_INFO *print_event_info) const {
5705 // Need 2 characters per one hex + 2 for 0x + 1 for \0
5706 char nonce_buf[NONCE_LENGTH * 2 + 2 + 1];
5707
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 str_to_hex(nonce_buf, reinterpret_cast<const char *>(nonce), NONCE_LENGTH);
5708
5709 6 IO_CACHE *const head = &print_event_info->head_cache;
5710
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 print_header(head, print_event_info, false);
5711
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_b_printf(head, "Encryption scheme: %d", crypto_scheme);
5712
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_b_printf(head, ", key_version: %d", key_version);
5713
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_b_printf(head, ", nonce: %s ", nonce_buf);
5714
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_b_printf(head,
5715 "\n# The rest of the binlog is encrypted with Percona Server 5.7 "
5716 "encryption!\n");
5717 6 }
5718 #endif
5719
5720 /**************************************************************************
5721 Rotate_log_event methods
5722 **************************************************************************/
5723
5724 #ifdef MYSQL_SERVER
5725
5726 /*
5727 Rotate_log_event::pack_info()
5728 */
5729
5730 1722 int Rotate_log_event::pack_info(Protocol *protocol) {
5731 char buf1[256], buf[22];
5732 1722 String tmp(buf1, sizeof(buf1), log_cs);
5733 1722 tmp.length(0);
5734
1/2
✓ Branch 0 taken 1722 times.
✗ Branch 1 not taken.
1722 tmp.append(new_log_ident, ident_len);
5735
1/2
✓ Branch 0 taken 1722 times.
✗ Branch 1 not taken.
1722 tmp.append(STRING_WITH_LEN(";pos="));
5736
2/4
✓ Branch 0 taken 1722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1722 times.
✗ Branch 3 not taken.
1722 tmp.append(llstr(pos, buf));
5737
1/2
✓ Branch 0 taken 1722 times.
✗ Branch 1 not taken.
1722 protocol->store_string(tmp.ptr(), tmp.length(), &my_charset_bin);
5738 1722 return 0;
5739 1722 }
5740 #endif // MYSQL_SERVER
5741
5742 /*
5743 Rotate_log_event::print()
5744 */
5745
5746 #ifndef MYSQL_SERVER
5747 1112 void Rotate_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
5748 char buf[22];
5749 1112 IO_CACHE *const head = &print_event_info->head_cache;
5750
5751
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 920 times.
1112 if (print_event_info->short_form) return;
5752
1/2
✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
920 print_header(head, print_event_info, false);
5753
1/2
✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
920 my_b_printf(head, "\tRotate to ");
5754
1/2
✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
920 if (new_log_ident) {
5755 [[maybe_unused]]
5756
1/2
✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
920 int write_res = my_b_write(head, pointer_cast<const uchar *>(new_log_ident),
5757 920 (uint)ident_len);
5758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 920 times.
920 assert(write_res == 0);
5759 }
5760
2/4
✓ Branch 0 taken 920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 920 times.
✗ Branch 3 not taken.
920 my_b_printf(head, " pos: %s\n", llstr(pos, buf));
5761 }
5762 #endif /* !MYSQL_SERVER */
5763
5764 /*
5765 Rotate_log_event::Rotate_log_event() (2 constructors)
5766 */
5767
5768 #ifdef MYSQL_SERVER
5769 44783 Rotate_log_event::Rotate_log_event(const char *new_log_ident_arg,
5770 size_t ident_len_arg, ulonglong pos_arg,
5771 44783 uint flags_arg)
5772 : binary_log::Rotate_event(new_log_ident_arg, ident_len_arg, flags_arg,
5773 pos_arg),
5774 Log_event(header(), footer(), Log_event::EVENT_NO_CACHE,
5775
1/2
✓ Branch 0 taken 44783 times.
✗ Branch 1 not taken.
44783 Log_event::EVENT_IMMEDIATE_LOGGING) {
5776 #ifndef NDEBUG
5777
1/2
✓ Branch 0 taken 44783 times.
✗ Branch 1 not taken.
44783 DBUG_TRACE;
5778 #endif
5779 44783 new_log_ident = new_log_ident_arg;
5780 44783 pos = pos_arg;
5781
1/2
✓ Branch 0 taken 44783 times.
✗ Branch 1 not taken.
44783 ident_len = ident_len_arg ? ident_len_arg : (uint)strlen(new_log_ident_arg);
5782 44783 flags = flags_arg;
5783
5784 #ifndef NDEBUG
5785 char buff[22];
5786
3/10
✓ Branch 0 taken 44784 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44784 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 44784 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
44783 DBUG_PRINT("enter", ("new_log_ident: %s pos: %s flags: %lu",
5787 new_log_ident_arg, llstr(pos_arg, buff), (ulong)flags));
5788 #endif
5789
2/2
✓ Branch 0 taken 13014 times.
✓ Branch 1 taken 31770 times.
44784 if (flags & DUP_NAME)
5790
1/2
✓ Branch 0 taken 13014 times.
✗ Branch 1 not taken.
13014 new_log_ident = my_strndup(key_memory_log_event, new_log_ident_arg,
5791 ident_len, MYF(MY_WME));
5792 44784 common_header->set_is_valid(new_log_ident != nullptr);
5793
2/2
✓ Branch 0 taken 23811 times.
✓ Branch 1 taken 20972 times.
44783 if (flags & RELAY_LOG) set_relay_log_event();
5794 44783 }
5795 #endif // MYSQL_SERVER
5796
5797 81951 Rotate_log_event::Rotate_log_event(
5798 81951 const char *buf, const Format_description_event *description_event)
5799 : binary_log::Rotate_event(buf, description_event),
5800
1/2
✓ Branch 0 taken 80549 times.
✗ Branch 1 not taken.
81951 Log_event(header(), footer()) {
5801
1/2
✓ Branch 0 taken 81950 times.
✗ Branch 1 not taken.
81950 DBUG_TRACE;
5802
3/4
✓ Branch 0 taken 80549 times.
✓ Branch 1 taken 1401 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80549 times.
81950 if (!is_valid()) return;
5803
3/8
✓ Branch 0 taken 81948 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81948 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 81948 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
81950 DBUG_PRINT("debug", ("new_log_ident: '%s'", new_log_ident));
5804
1/2
✓ Branch 0 taken 81951 times.
✗ Branch 1 not taken.
81948 }
5805
5806 /*
5807 Rotate_log_event::write()
5808 */
5809
5810 #ifdef MYSQL_SERVER
5811 43429 bool Rotate_log_event::write(Basic_ostream *ostream) {
5812 char buf[Binary_log_event::ROTATE_HEADER_LEN];
5813 43429 int8store(buf + R_POS_OFFSET, pos);
5814 return (
5815
1/2
✓ Branch 0 taken 43430 times.
✗ Branch 1 not taken.
43429 write_header(ostream, Binary_log_event::ROTATE_HEADER_LEN + ident_len) ||
5816
2/4
✓ Branch 0 taken 43429 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43429 times.
✗ Branch 3 not taken.
43430 wrapper_my_b_safe_write(ostream, (uchar *)buf,
5817 43430 Binary_log_event::ROTATE_HEADER_LEN) ||
5818
2/4
✓ Branch 0 taken 43430 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43430 times.
✗ Branch 3 not taken.
43429 wrapper_my_b_safe_write(ostream,
5819 43429 pointer_cast<const uchar *>(new_log_ident),
5820
1/2
✓ Branch 0 taken 43430 times.
✗ Branch 1 not taken.
130288 (uint)ident_len) ||
5821
2/4
✓ Branch 0 taken 43429 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 43429 times.
86859 write_footer(ostream));
5822 }
5823
5824 /*
5825 Got a rotate log event from the master.
5826
5827 This is mainly used so that we can later figure out the logname and
5828 position for the master.
5829
5830 We can't rotate the slave's BINlog as this will cause infinitive rotations
5831 in a A -> B -> A setup.
5832 The NOTES below is a wrong comment which will disappear when 4.1 is merged.
5833
5834 This must only be called from the Slave SQL thread, since it calls
5835 flush_relay_log_info().
5836
5837 @retval
5838 0 ok
5839 */
5840 53594 int Rotate_log_event::do_update_pos(Relay_log_info *rli) {
5841 53594 int error = 0;
5842
1/2
✓ Branch 0 taken 53594 times.
✗ Branch 1 not taken.
53594 DBUG_TRACE;
5843 #ifndef NDEBUG
5844 char buf[32];
5845 #endif
5846
5847
3/8
✓ Branch 0 taken 53594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 53594 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
53594 DBUG_PRINT("info", ("server_id=%lu; ::server_id=%lu", (ulong)this->server_id,
5848 (ulong)::server_id));
5849
3/8
✓ Branch 0 taken 53594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 53594 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
53594 DBUG_PRINT("info", ("new_log_ident: %s", this->new_log_ident));
5850
3/10
✓ Branch 0 taken 53594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53594 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 53594 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
53594 DBUG_PRINT("info", ("pos: %s", llstr(this->pos, buf)));
5851
5852
10/16
✓ Branch 0 taken 53594 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 53592 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
53595 DBUG_EXECUTE_IF("block_on_master_pos_4_rotate", {
5853 if (server_id == 1 && pos == 4) {
5854 std::string action =
5855 "now signal signal.reach_pos_4_rotate_event wait_for "
5856 "signal.rotate_event_continue";
5857 assert(
5858 !debug_sync_set_action(current_thd, action.c_str(), action.size()));
5859 }
5860 });
5861
5862 /*
5863 If we are in a transaction or in a group: the only normal case is
5864 when the I/O thread was copying a big transaction, then it was
5865 stopped and restarted: we have this in the relay log:
5866
5867 BEGIN
5868 ...
5869 ROTATE (a fake one)
5870 ...
5871 COMMIT or ROLLBACK
5872
5873 In that case, we don't want to touch the coordinates which
5874 correspond to the beginning of the transaction. Starting from
5875 5.0.0, there also are some rotates from the slave itself, in the
5876 relay log, which shall not change the group positions.
5877 */
5878
5879 /*
5880 The way we check if SQL thread is currently in a group is different
5881 for STS and MTS.
5882 */
5883
1/2
✓ Branch 0 taken 53594 times.
✗ Branch 1 not taken.
53594 bool in_group = rli->is_parallel_exec()
5884
2/2
✓ Branch 0 taken 53454 times.
✓ Branch 1 taken 140 times.
53594 ? (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)
5885
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 : rli->is_in_group();
5886
5887
2/2
✓ Branch 0 taken 5119 times.
✓ Branch 1 taken 17571 times.
22690 if ((server_id != ::server_id || rli->replicate_same_server_id) &&
5888
8/8
✓ Branch 0 taken 22690 times.
✓ Branch 1 taken 30904 times.
✓ Branch 2 taken 30907 times.
✓ Branch 3 taken 5116 times.
✓ Branch 4 taken 30768 times.
✓ Branch 5 taken 139 times.
✓ Branch 6 taken 30768 times.
✓ Branch 7 taken 22826 times.
76284 !is_relay_log_event() && !in_group) {
5889
5/6
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30602 times.
✓ Branch 3 taken 166 times.
✓ Branch 4 taken 30602 times.
✓ Branch 5 taken 166 times.
61370 if (!is_mts_db_partitioned(rli) &&
5890
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 30598 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
30602 (server_id != ::server_id || rli->replicate_same_server_id)) {
5891 // force the coordinator to start a new binlog segment.
5892 30602 static_cast<Mts_submode_logical_clock *>(rli->current_mts_submode)
5893 30602 ->start_new_group();
5894 }
5895
3/4
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30696 times.
✓ Branch 3 taken 72 times.
30768 if (rli->is_parallel_exec()) {
5896 /*
5897 Rotate events are special events that are handled as a
5898 synchronization point. For that reason, the checkpoint
5899 routine is being called here.
5900 */
5901
2/4
✓ Branch 0 taken 30696 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30696 times.
30696 if ((error = mta_checkpoint_routine(rli, false))) goto err;
5902 }
5903
5904
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 mysql_mutex_lock(&rli->data_lock);
5905
3/8
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30768 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30768 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
30768 DBUG_PRINT("info", ("old group_master_log_name: '%s' "
5906 "old group_master_log_pos: %lu",
5907 rli->get_group_master_log_name(),
5908 (ulong)rli->get_group_master_log_pos()));
5909
5910 61536 memcpy(const_cast<char *>(rli->get_group_master_log_name()), new_log_ident,
5911 30768 ident_len + 1);
5912
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 rli->notify_group_master_log_name_update();
5913 /*
5914 Execution coordinate update by Rotate itself needs forced flush
5915 otherwise in crash case MTS won't be able to find the starting point
5916 for recovery.
5917 It is safe to update the last executed coordinates because all Worker
5918 assignments prior to Rotate has been already processed (as well as
5919 above call to @c mta_checkpoint_routine has harvested their
5920 contribution to the last executed coordinates).
5921 */
5922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30768 times.
30768 if ((error = rli->inc_group_relay_log_pos(
5923
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 pos, false /* need_data_lock=false */, true /* force flush */))) {
5924 mysql_mutex_unlock(&rli->data_lock);
5925 goto err;
5926 }
5927
5928
3/8
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30768 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30768 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
30768 DBUG_PRINT("info", ("new group_master_log_name: '%s' "
5929 "new group_master_log_pos: %lu",
5930 rli->get_group_master_log_name(),
5931 (ulong)rli->get_group_master_log_pos()));
5932
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 mysql_mutex_unlock(&rli->data_lock);
5933
5934
3/4
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30696 times.
✓ Branch 3 taken 72 times.
30768 if (rli->is_parallel_exec()) {
5935
4/4
✓ Branch 0 taken 17894 times.
✓ Branch 1 taken 12802 times.
✓ Branch 2 taken 5632 times.
✓ Branch 3 taken 12262 times.
30696 bool real_event = server_id && !is_artificial_event();
5936
3/4
✓ Branch 0 taken 5632 times.
✓ Branch 1 taken 25064 times.
✓ Branch 2 taken 30696 times.
✗ Branch 3 not taken.
36328 rli->reset_notified_checkpoint(
5937 5632 0, real_event ? common_header->when.tv_sec + (time_t)exec_time : 0,
5938 real_event);
5939 }
5940
5941 /*
5942 Reset thd->variables.option_bits and sql_mode etc, because this could be
5943 the signal of a master's downgrade from 5.0 to 4.0. However, no need to
5944 reset rli_description_event: indeed, if the next master is 5.0
5945 (even 5.0.1) we will soon get a Format_desc; if the next master is 4.0
5946 then the events are in the slave's format (conversion).
5947 */
5948
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 set_slave_thread_options(thd);
5949
1/2
✓ Branch 0 taken 30768 times.
✗ Branch 1 not taken.
30768 set_slave_thread_default_charset(thd, rli);
5950 30768 thd->variables.sql_mode = global_system_variables.sql_mode;
5951 30768 thd->variables.auto_increment_increment =
5952 30768 thd->variables.auto_increment_offset = 1;
5953 /*
5954 Rotate_log_events are generated on Slaves with server_id=0
5955 for all the ignored events, so that the positions in the repository
5956 is updated properly even for ignored events.
5957
5958 This kind of Rotate_log_event is generated when
5959
5960 1) the event is generated on the same host and reached due
5961 to circular replication (server_id == ::server_id)
5962
5963 2) the event is from the host which is listed in ignore_server_ids
5964
5965 3) IO thread is receiving HEARTBEAT event from the master
5966
5967 4) IO thread is receiving PREVIOUS_GTID_LOG_EVENT from the master.
5968
5969 We have to free thd's mem_root here after we update the positions
5970 in the repository table. Otherwise, imagine a situation where
5971 Slave is keep getting ignored events only and no other (non-ignored)
5972 events from the Master, Slave never executes free_root (that generally
5973 happens from Query_log_event::do_apply_event or
5974 Rows_log_event::do_apply_event when they find end of the group event).
5975 */
5976
3/4
✓ Branch 0 taken 12831 times.
✓ Branch 1 taken 17937 times.
✓ Branch 2 taken 12831 times.
✗ Branch 3 not taken.
30768 if (server_id == 0) thd->mem_root->ClearForReuse();
5977 } else
5978 22826 rli->inc_event_relay_log_pos();
5979
5980 53594 err:
5981 53594 return error;
5982 53594 }
5983
5984 53786 Log_event::enum_skip_reason Rotate_log_event::do_shall_skip(
5985 Relay_log_info *rli) {
5986 53786 enum_skip_reason reason = Log_event::do_shall_skip(rli);
5987
5988
2/3
✓ Branch 0 taken 36227 times.
✓ Branch 1 taken 17559 times.
✗ Branch 2 not taken.
53786 switch (reason) {
5989 36227 case Log_event::EVENT_SKIP_NOT:
5990 case Log_event::EVENT_SKIP_COUNT:
5991 36227 return Log_event::EVENT_SKIP_NOT;
5992
5993 17559 case Log_event::EVENT_SKIP_IGNORE:
5994 17559 return Log_event::EVENT_SKIP_IGNORE;
5995 }
5996 assert(0);
5997 return Log_event::EVENT_SKIP_NOT; // To keep compiler happy
5998 }
5999
6000 /**************************************************************************
6001 Intvar_log_event methods
6002 **************************************************************************/
6003
6004 /*
6005 Intvar_log_event::pack_info()
6006 */
6007
6008 22085 int Intvar_log_event::pack_info(Protocol *protocol) {
6009 char buf[256], *pos;
6010
2/4
✓ Branch 0 taken 22085 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22085 times.
✗ Branch 3 not taken.
22085 pos = strmake(buf, (get_var_type_string()).c_str(), sizeof(buf) - 23);
6011 22085 *pos++ = '=';
6012
1/2
✓ Branch 0 taken 22085 times.
✗ Branch 1 not taken.
22085 pos = longlong10_to_str(val, pos, -10);
6013
1/2
✓ Branch 0 taken 22085 times.
✗ Branch 1 not taken.
22085 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
6014 22085 return 0;
6015 }
6016 #endif // MYSQL_SERVER
6017
6018 /*
6019 Intvar_log_event::Intvar_log_event()
6020 */
6021 102667 Intvar_log_event::Intvar_log_event(
6022 102667 const char *buf, const Format_description_event *description_event)
6023 : binary_log::Intvar_event(buf, description_event),
6024
1/2
✓ Branch 0 taken 82546 times.
✗ Branch 1 not taken.
102667 Log_event(header(), footer()) {
6025
1/2
✓ Branch 0 taken 102667 times.
✗ Branch 1 not taken.
102667 DBUG_TRACE;
6026 102667 }
6027
6028 /*
6029 Intvar_log_event::write()
6030 */
6031
6032 #ifdef MYSQL_SERVER
6033 87466 bool Intvar_log_event::write(Basic_ostream *ostream) {
6034 uchar buf[9];
6035 87466 buf[I_TYPE_OFFSET] = (uchar)type;
6036 87466 int8store(buf + I_VAL_OFFSET, val);
6037
1/2
✓ Branch 0 taken 87466 times.
✗ Branch 1 not taken.
87466 return (write_header(ostream, sizeof(buf)) ||
6038
3/6
✓ Branch 0 taken 87466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 87466 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 87466 times.
✗ Branch 5 not taken.
174932 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
6039
2/4
✓ Branch 0 taken 87466 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 87466 times.
174932 write_footer(ostream));
6040 }
6041 #endif
6042
6043 /*
6044 Intvar_log_event::print()
6045 */
6046
6047 #ifndef MYSQL_SERVER
6048 20096 void Intvar_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
6049 20096 char llbuff[22] = {0};
6050 20096 const char *msg = nullptr;
6051 20096 IO_CACHE *const head = &print_event_info->head_cache;
6052
6053
2/2
✓ Branch 0 taken 20094 times.
✓ Branch 1 taken 2 times.
20096 if (!print_event_info->short_form) {
6054
1/2
✓ Branch 0 taken 20094 times.
✗ Branch 1 not taken.
20094 print_header(head, print_event_info, false);
6055
1/2
✓ Branch 0 taken 20094 times.
✗ Branch 1 not taken.
20094 my_b_printf(head, "\tIntvar\n");
6056 }
6057
6058
1/2
✓ Branch 0 taken 20096 times.
✗ Branch 1 not taken.
20096 my_b_printf(head, "SET ");
6059
2/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20092 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
20096 switch (type) {
6060 4 case LAST_INSERT_ID_EVENT:
6061 4 msg = "LAST_INSERT_ID";
6062 4 break;
6063 20092 case INSERT_ID_EVENT:
6064 20092 msg = "INSERT_ID";
6065 20092 break;
6066 #ifdef WITH_WSREP
6067 case BINLOG_CONTROL_EVENT:
6068 msg = "BINLOG_CONTROL";
6069 assert(0);
6070 break;
6071 #endif
6072 case INVALID_INT_EVENT:
6073 default: // cannot happen
6074 msg = "INVALID_INT";
6075 break;
6076 }
6077
1/2
✓ Branch 0 taken 20096 times.
✗ Branch 1 not taken.
20096 my_b_printf(head, "%s=%s%s\n", msg, llstr(val, llbuff),
6078
1/2
✓ Branch 0 taken 20096 times.
✗ Branch 1 not taken.
20096 print_event_info->delimiter);
6079 20096 }
6080 #endif
6081
6082 #if defined(MYSQL_SERVER)
6083
6084 /*
6085 Intvar_log_event::do_apply_event()
6086 */
6087
6088 37954 int Intvar_log_event::do_apply_event(Relay_log_info const *rli) {
6089 /*
6090 We are now in a statement until the associated query log event has
6091 been processed.
6092 */
6093 37954 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
6094
6095
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 37942 times.
37954 if (rli->deferred_events_collecting) return rli->deferred_events->add(this);
6096
6097
3/4
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 37822 times.
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
37942 switch (type) {
6098 89 case LAST_INSERT_ID_EVENT:
6099 89 thd->first_successful_insert_id_in_prev_stmt = val;
6100 89 break;
6101 37822 case INSERT_ID_EVENT:
6102 37822 thd->force_one_auto_inc_interval(val);
6103 37822 break;
6104 #ifdef WITH_WSREP
6105 31 case BINLOG_CONTROL_EVENT:
6106
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (val == 0) {
6107 31 thd->variables.option_bits &= ~(OPTION_BIN_LOG);
6108 }
6109 31 break;
6110 #endif /* WITH_WSREP */
6111 }
6112 37942 return 0;
6113 }
6114
6115 2 int Intvar_log_event::do_update_pos(Relay_log_info *rli) {
6116 2 rli->inc_event_relay_log_pos();
6117 2 return 0;
6118 }
6119
6120 37918 Log_event::enum_skip_reason Intvar_log_event::do_shall_skip(
6121 Relay_log_info *rli) {
6122 /*
6123 It is a common error to set the slave skip counter to 1 instead of
6124 2 when recovering from an insert which used a auto increment,
6125 rand, or user var. Therefore, if the slave skip counter is 1, we
6126 just say that this event should be skipped by ignoring it, meaning
6127 that we do not change the value of the slave skip counter since it
6128 will be decreased by the following insert event.
6129 */
6130 37918 return continue_group(rli);
6131 }
6132
6133 /**************************************************************************
6134 Rand_log_event methods
6135 **************************************************************************/
6136
6137 1 int Rand_log_event::pack_info(Protocol *protocol) {
6138 char buf1[256], *pos;
6139 1 pos = my_stpcpy(buf1, "rand_seed1=");
6140
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 pos = longlong10_to_str(seed1, pos, 10);
6141 1 pos = my_stpcpy(pos, ",rand_seed2=");
6142
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 pos = longlong10_to_str(seed2, pos, 10);
6143
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 protocol->store_string(buf1, (uint)(pos - buf1), &my_charset_bin);
6144 1 return 0;
6145 }
6146 #endif // MYSQL_SERVER
6147
6148 1001 Rand_log_event::Rand_log_event(
6149 1001 const char *buf, const Format_description_event *description_event)
6150 : binary_log::Rand_event(buf, description_event),
6151
1/2
✓ Branch 0 taken 994 times.
✗ Branch 1 not taken.
1001 Log_event(header(), footer()) {
6152
1/2
✓ Branch 0 taken 1001 times.
✗ Branch 1 not taken.
1001 DBUG_TRACE;
6153 1001 }
6154
6155 #ifdef MYSQL_SERVER
6156 2098 bool Rand_log_event::write(Basic_ostream *ostream) {
6157 uchar buf[16];
6158 2098 int8store(buf + RAND_SEED1_OFFSET, seed1);
6159 2098 int8store(buf + RAND_SEED2_OFFSET, seed2);
6160
1/2
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
2098 return (write_header(ostream, sizeof(buf)) ||
6161
3/6
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2098 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2098 times.
✗ Branch 5 not taken.
4196 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
6162
2/4
✓ Branch 0 taken 2098 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2098 times.
4196 write_footer(ostream));
6163 }
6164 #endif
6165
6166 #ifndef MYSQL_SERVER
6167 4 void Rand_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
6168 4 IO_CACHE *const head = &print_event_info->head_cache;
6169
6170 char llbuff[22], llbuff2[22];
6171
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!print_event_info->short_form) {
6172
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 print_header(head, print_event_info, false);
6173
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_b_printf(head, "\tRand\n");
6174 }
6175
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_b_printf(head, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s%s\n",
6176
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 llstr(seed1, llbuff), llstr(seed2, llbuff2),
6177
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 print_event_info->delimiter);
6178 4 }
6179 #endif /* !MYSQL_SERVER */
6180
6181 #if defined(MYSQL_SERVER)
6182 992 int Rand_log_event::do_apply_event(Relay_log_info const *rli) {
6183 /*
6184 We are now in a statement until the associated query log event has
6185 been processed.
6186 */
6187 992 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
6188
6189
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 991 times.
992 if (rli->deferred_events_collecting) return rli->deferred_events->add(this);
6190
6191 991 thd->rand.seed1 = (ulong)seed1;
6192 991 thd->rand.seed2 = (ulong)seed2;
6193 991 return 0;
6194 }
6195
6196 int Rand_log_event::do_update_pos(Relay_log_info *rli) {
6197 rli->inc_event_relay_log_pos();
6198 return 0;
6199 }
6200
6201 992 Log_event::enum_skip_reason Rand_log_event::do_shall_skip(Relay_log_info *rli) {
6202 /*
6203 It is a common error to set the slave skip counter to 1 instead of
6204 2 when recovering from an insert which used a auto increment,
6205 rand, or user var. Therefore, if the slave skip counter is 1, we
6206 just say that this event should be skipped by ignoring it, meaning
6207 that we do not change the value of the slave skip counter since it
6208 will be decreased by the following insert event.
6209 */
6210 992 return continue_group(rli);
6211 }
6212
6213 /**
6214 Exec deferred Int-, Rand- and User- var events prefixing
6215 a Query-log-event event.
6216
6217 @param thd THD handle
6218
6219 @return false on success, true if a failure in an event applying occurred.
6220 */
6221 535134 bool slave_execute_deferred_events(THD *thd) {
6222 535134 bool res = false;
6223 535134 Relay_log_info *rli = thd->rli_slave;
6224 #ifdef WITH_WSREP
6225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 535134 times.
535134 if (thd->wsrep_applier) rli = thd->wsrep_rli;
6226 #endif /* WITH_WSREP */
6227
6228
4/6
✓ Branch 0 taken 535692 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1251 times.
✓ Branch 3 taken 534441 times.
✓ Branch 4 taken 1610 times.
✗ Branch 5 not taken.
535134 assert(rli && (!rli->deferred_events_collecting || rli->deferred_events));
6229
6230
4/6
✓ Branch 0 taken 1251 times.
✓ Branch 1 taken 534800 times.
✓ Branch 2 taken 1350 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 536093 times.
✗ Branch 5 not taken.
536051 if (!rli->deferred_events_collecting || rli->deferred_events->is_empty())
6231 536093 return res;
6232
6233 res = rli->deferred_events->execute(rli);
6234 7 rli->deferred_events->rewind();
6235 7 return res;
6236 }
6237
6238 /**************************************************************************
6239 Xid_log_event methods
6240 **************************************************************************/
6241
6242 8082 int Xid_log_event::pack_info(Protocol *protocol) {
6243 char buf[128], *pos;
6244 8082 pos = my_stpcpy(buf, "COMMIT /* xid=");
6245
1/2
✓ Branch 0 taken 8082 times.
✗ Branch 1 not taken.
8082 pos = longlong10_to_str(xid, pos, 10);
6246 8082 pos = my_stpcpy(pos, " */");
6247
1/2
✓ Branch 0 taken 8082 times.
✗ Branch 1 not taken.
8082 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
6248 8082 return 0;
6249 }
6250 #endif // MYSQL_SERVER
6251
6252 1015980 Xid_log_event::Xid_log_event(const char *buf,
6253 1015980 const Format_description_event *description_event)
6254 : binary_log::Xid_event(buf, description_event),
6255
1/2
✓ Branch 0 taken 1015980 times.
✗ Branch 1 not taken.
1015980 Xid_apply_log_event(header(), footer()) {
6256
1/2
✓ Branch 0 taken 1015980 times.
✗ Branch 1 not taken.
1015980 DBUG_TRACE;
6257 1015980 }
6258
6259 #ifdef MYSQL_SERVER
6260 1722004 bool Xid_log_event::write(Basic_ostream *ostream) {
6261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1722012 times.
1722004 DBUG_EXECUTE_IF("do_not_write_xid", return 0;);
6262 1722012 return (write_header(ostream, sizeof(xid)) ||
6263
2/4
✓ Branch 0 taken 1722022 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1722019 times.
✗ Branch 3 not taken.
3444045 wrapper_my_b_safe_write(ostream, (uchar *)&xid, sizeof(xid)) ||
6264
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1722022 times.
3444041 write_footer(ostream));
6265 }
6266 #endif
6267
6268 #ifndef MYSQL_SERVER
6269 27847 void Xid_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
6270 27847 IO_CACHE *const head = &print_event_info->head_cache;
6271
6272
2/2
✓ Branch 0 taken 27330 times.
✓ Branch 1 taken 517 times.
27847 if (!print_event_info->short_form) {
6273 char buf[64];
6274
1/2
✓ Branch 0 taken 27330 times.
✗ Branch 1 not taken.
27330 longlong10_to_str(xid, buf, 10);
6275
6276
1/2
✓ Branch 0 taken 27330 times.
✗ Branch 1 not taken.
27330 print_header(head, print_event_info, false);
6277
1/2
✓ Branch 0 taken 27330 times.
✗ Branch 1 not taken.
27330 my_b_printf(head, "\tXid = %s\n", buf);
6278 }
6279 27847 my_b_printf(head, "COMMIT%s\n", print_event_info->delimiter);
6280 27847 }
6281 #endif /* !MYSQL_SERVER */
6282
6283 #if defined(MYSQL_SERVER)
6284 /**
6285 The methods combines few commit actions to make it usable
6286 as in the single- so multi- threaded case.
6287
6288 @param thd_arg a pointer to THD handle
6289 @return false as success and
6290 true as an error
6291 */
6292
6293 149789 bool Xid_log_event::do_commit(THD *thd_arg) {
6294
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 149788 times.
149789 DBUG_EXECUTE_IF("dbug.reached_commit",
6295 { DBUG_SET("+d,dbug.enabled_commit"); });
6296 149790 bool error = trans_commit(thd_arg); /* Automatically rolls back on error. */
6297
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 149036 times.
148646 DBUG_EXECUTE_IF("crash_after_apply",
6298 sql_print_information("Crashing crash_after_apply.");
6299 DBUG_SUICIDE(););
6300 149036 thd_arg->mdl_context.release_transactional_locks();
6301
6302 149628 error |= (mysql_bin_log.gtid_end_transaction(thd_arg) != 0);
6303
6304 /*
6305 The parser executing a SQLCOM_COMMIT or SQLCOM_ROLLBACK will reset the
6306 tx isolation level and access mode when the statement is finishing a
6307 transaction.
6308
6309 For replicated workload, when dealing with pure transactional workloads,
6310 there will be no QUERY(COMMIT) finishing a transaction, but a
6311 Xid_log_event instead.
6312
6313 So, if the slave applier changed the current transaction isolation level,
6314 it needs to be restored to the session default value once the current
6315 transaction has been committed.
6316 */
6317 149667 trans_reset_one_shot_chistics(thd);
6318
6319 /*
6320 Increment the global status commit count variable
6321 */
6322
2/2
✓ Branch 0 taken 149569 times.
✓ Branch 1 taken 144 times.
149713 if (!error) thd_arg->status_var.com_stat[SQLCOM_COMMIT]++;
6323
6324 149713 return error;
6325 }
6326
6327 /**
6328 Worker commits Xid transaction and in case of its transactional
6329 info table marks the current group as done in the Coordinator's
6330 Group Assigned Queue.
6331
6332 @return zero as success or non-zero as an error
6333 */
6334 149825 int Xid_apply_log_event::do_apply_event_worker(Slave_worker *w) {
6335
1/2
✓ Branch 0 taken 149848 times.
✗ Branch 1 not taken.
149825 DBUG_TRACE;
6336 149848 int error = 0;
6337 149848 bool skipped_commit_pos = true;
6338
6339
1/2
✓ Branch 0 taken 149850 times.
✗ Branch 1 not taken.
149848 lex_start(thd);
6340
1/2
✓ Branch 0 taken 149850 times.
✗ Branch 1 not taken.
149850 mysql_reset_thd_for_next_command(thd);
6341 149850 Slave_committed_queue *coordinator_gaq = w->c_rli->gaq;
6342
6343 /* For a slave Xid_log_event is COMMIT */
6344
1/2
✓ Branch 0 taken 149852 times.
✗ Branch 1 not taken.
149850 query_logger.general_log_print(thd, COM_QUERY,
6345 "COMMIT /* implicit, from Xid_log_event */");
6346
6347
3/8
✓ Branch 0 taken 149853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149853 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 149853 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
149852 DBUG_PRINT(
6348 "mts",
6349 ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
6350 w->get_group_master_log_name(), w->get_group_master_log_pos(),
6351 w->get_group_relay_log_name(), w->get_group_relay_log_pos(),
6352 w->get_event_relay_log_name(), w->get_event_relay_log_pos()));
6353
6354
5/8
✓ Branch 0 taken 149853 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 149823 times.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
149853 DBUG_EXECUTE_IF("crash_before_update_pos",
6355 sql_print_information("Crashing crash_before_update_pos.");
6356 DBUG_SUICIDE(););
6357
6358
2/4
✓ Branch 0 taken 149823 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 149823 times.
149823 DBUG_EXECUTE_IF("simulate_commit_failure", {
6359 thd->get_transaction()->xid_state()->set_state(XID_STATE::XA_IDLE);
6360 });
6361
6362 149823 ulong gaq_idx = mts_group_idx;
6363
1/2
✓ Branch 0 taken 149823 times.
✗ Branch 1 not taken.
149823 Slave_job_group *ptr_group = coordinator_gaq->get_job_group(gaq_idx);
6364
6365
5/6
✓ Branch 0 taken 149822 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149491 times.
✓ Branch 3 taken 331 times.
✓ Branch 4 taken 149439 times.
✓ Branch 5 taken 384 times.
299315 if (!thd->get_transaction()->xid_state()->check_in_xa(false) &&
6366
3/4
✓ Branch 0 taken 149492 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149439 times.
✓ Branch 3 taken 53 times.
149491 w->is_transactional()) {
6367 /*
6368 Regular (not XA) transaction updates the transactional info table
6369 along with the main transaction. Otherwise, the local flag turned
6370 and given its value the info table is updated after do_commit.
6371 todo: the flag won't be need upon the full xa crash-safety bug76233
6372 gets fixed.
6373 */
6374 149439 skipped_commit_pos = false;
6375
4/6
✓ Branch 0 taken 149439 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149438 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 149433 times.
149439 if ((error = w->commit_positions(this, ptr_group, w->is_transactional())))
6376 5 goto err;
6377 }
6378
6379
3/8
✓ Branch 0 taken 149817 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 149818 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 149818 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
149817 DBUG_PRINT(
6380 "mts",
6381 ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
6382 w->get_group_master_log_name(), w->get_group_master_log_pos(),
6383 w->get_group_relay_log_name(), w->get_group_relay_log_pos(),
6384 w->get_event_relay_log_name(), w->get_event_relay_log_pos()));
6385
6386
5/8
✓ Branch 0 taken 149818 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 149788 times.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
149818 DBUG_EXECUTE_IF(
6387 "crash_after_update_pos_before_apply",
6388 sql_print_information("Crashing crash_after_update_pos_before_apply.");
6389 DBUG_SUICIDE(););
6390
6391
1/2
✓ Branch 0 taken 149533 times.
✗ Branch 1 not taken.
149788 error = do_commit(thd);
6392
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 149384 times.
149533 if (error) {
6393
3/4
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 142 times.
✗ Branch 3 not taken.
149 if (!skipped_commit_pos) w->rollback_positions(ptr_group);
6394 } else {
6395
5/8
✓ Branch 0 taken 149458 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 149428 times.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
149384 DBUG_EXECUTE_IF(
6396 "crash_after_commit_before_update_pos",
6397 sql_print_information("Crashing "
6398 "crash_after_commit_before_update_pos.");
6399 DBUG_SUICIDE(););
6400
2/2
✓ Branch 0 taken 149053 times.
✓ Branch 1 taken 375 times.
149428 if (skipped_commit_pos)
6401
2/4
✓ Branch 0 taken 375 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 375 times.
✗ Branch 3 not taken.
375 error = w->commit_positions(this, ptr_group, w->is_transactional());
6402 }
6403 149053 err:
6404 149613 return error;
6405 149582 }
6406
6407 354 int Xid_apply_log_event::do_apply_event(Relay_log_info const *rli) {
6408
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 DBUG_TRACE;
6409 354 int error = 0;
6410 char saved_group_master_log_name[FN_REFLEN];
6411 char saved_group_relay_log_name[FN_REFLEN];
6412 volatile my_off_t saved_group_master_log_pos;
6413 volatile my_off_t saved_group_relay_log_pos;
6414
6415 char new_group_master_log_name[FN_REFLEN];
6416 char new_group_relay_log_name[FN_REFLEN];
6417 volatile my_off_t new_group_master_log_pos;
6418 volatile my_off_t new_group_relay_log_pos;
6419
6420
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 lex_start(thd);
6421
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 mysql_reset_thd_for_next_command(thd);
6422 /*
6423 Anonymous GTID ownership may be released here if the last
6424 statement before XID updated a non-transactional table and was
6425 written to the binary log as a separate transaction (either
6426 because binlog_format=row or because
6427 binlog_direct_non_transactional_updates=1). So we need to
6428 re-acquire anonymous ownership.
6429 */
6430
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 gtid_reacquire_ownership_if_anonymous(thd);
6431 354 Relay_log_info *rli_ptr = const_cast<Relay_log_info *>(rli);
6432
6433 /* For a slave Xid_log_event is COMMIT */
6434
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 query_logger.general_log_print(thd, COM_QUERY,
6435 "COMMIT /* implicit, from Xid_log_event */");
6436
6437
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 mysql_mutex_lock(&rli_ptr->data_lock);
6438
6439 /*
6440 Save the rli positions. We need them to temporarily reset the positions
6441 just before the commit.
6442 */
6443
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 strmake(saved_group_master_log_name, rli_ptr->get_group_master_log_name(),
6444 FN_REFLEN - 1);
6445 354 saved_group_master_log_pos = rli_ptr->get_group_master_log_pos();
6446
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 strmake(saved_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
6447 FN_REFLEN - 1);
6448 354 saved_group_relay_log_pos = rli_ptr->get_group_relay_log_pos();
6449
6450
3/8
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 354 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 354 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
354 DBUG_PRINT(
6451 "info",
6452 ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
6453 rli_ptr->get_group_master_log_name(),
6454 rli_ptr->get_group_master_log_pos(), rli_ptr->get_group_relay_log_name(),
6455 rli_ptr->get_group_relay_log_pos(), rli_ptr->get_event_relay_log_name(),
6456 rli_ptr->get_event_relay_log_pos()));
6457
6458
2/8
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 354 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
354 DBUG_EXECUTE_IF("crash_before_update_pos",
6459 sql_print_information("Crashing crash_before_update_pos.");
6460 DBUG_SUICIDE(););
6461
6462 /*
6463 We need to update the positions in here to make it transactional.
6464 */
6465 354 rli_ptr->inc_event_relay_log_pos();
6466 354 rli_ptr->set_group_relay_log_pos(rli_ptr->get_event_relay_log_pos());
6467
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 rli_ptr->set_group_relay_log_name(rli_ptr->get_event_relay_log_name());
6468
6469
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 if (common_header->log_pos) // 3.23 binlogs don't have log_posx
6470 354 rli_ptr->set_group_master_log_pos(common_header->log_pos);
6471
6472
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 const bool already_logged_transaction = is_already_logged_transaction(thd);
6473 /*
6474 rli repository being transactional means replication is crash safe.
6475 Positions are written into transactional tables ahead of commit and the
6476 changes are made permanent during commit.
6477 XA transactional does not actually commit so has to defer its flush_info().
6478 */
6479
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 if (!thd->get_transaction()->xid_state()->check_in_xa(false) &&
6480
9/10
✓ Branch 0 taken 352 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 352 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 351 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 336 times.
✓ Branch 7 taken 15 times.
✓ Branch 8 taken 336 times.
✓ Branch 9 taken 18 times.
354 rli_ptr->is_transactional() && !already_logged_transaction) {
6481 336 if ((error =
6482
2/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
336 rli_ptr->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT)))
6483 goto err;
6484 }
6485
6486
3/8
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 354 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 354 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
354 DBUG_PRINT(
6487 "info",
6488 ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
6489 rli_ptr->get_group_master_log_name(),
6490 rli_ptr->get_group_master_log_pos(), rli_ptr->get_group_relay_log_name(),
6491 rli_ptr->get_group_relay_log_pos(), rli_ptr->get_event_relay_log_name(),
6492 rli_ptr->get_event_relay_log_pos()));
6493
6494
2/8
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 354 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
354 DBUG_EXECUTE_IF(
6495 "crash_after_update_pos_before_apply",
6496 sql_print_information("Crashing crash_after_update_pos_before_apply.");
6497 DBUG_SUICIDE(););
6498
6499 /**
6500 Commit operation expects the global transaction state variable 'xa_state'to
6501 be set to 'XA_NOTR'. In order to simulate commit failure we set
6502 the 'xa_state' to 'XA_IDLE' so that the commit reports 'ER_XAER_RMFAIL'
6503 error.
6504 */
6505
2/4
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 354 times.
354 DBUG_EXECUTE_IF("simulate_commit_failure", {
6506 thd->get_transaction()->xid_state()->set_state(XID_STATE::XA_IDLE);
6507 });
6508
6509 /*
6510 Save the new rli positions. These positions will be set back to group*
6511 positions on successful completion of the commit operation.
6512 */
6513
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 strmake(new_group_master_log_name, rli_ptr->get_group_master_log_name(),
6514 FN_REFLEN - 1);
6515 354 new_group_master_log_pos = rli_ptr->get_group_master_log_pos();
6516
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 strmake(new_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
6517 FN_REFLEN - 1);
6518 354 new_group_relay_log_pos = rli_ptr->get_group_relay_log_pos();
6519 /*
6520 Rollback positions in memory just before commit. Position values will be
6521 reset to their new values only on successful commit operation.
6522 */
6523
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 rli_ptr->set_group_master_log_name(saved_group_master_log_name);
6524 354 rli_ptr->set_group_master_log_pos(saved_group_master_log_pos);
6525
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 rli_ptr->notify_group_master_log_name_update();
6526
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 rli_ptr->set_group_relay_log_name(saved_group_relay_log_name);
6527 354 rli_ptr->set_group_relay_log_pos(saved_group_relay_log_pos);
6528
6529
3/8
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 354 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 354 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
354 DBUG_PRINT("info", ("Rolling back to group master %s %llu group relay %s"
6530 " %llu\n",
6531 rli_ptr->get_group_master_log_name(),
6532 rli_ptr->get_group_master_log_pos(),
6533 rli_ptr->get_group_relay_log_name(),
6534 rli_ptr->get_group_relay_log_pos()));
6535
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 mysql_mutex_unlock(&rli_ptr->data_lock);
6536
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 error = do_commit(thd);
6537
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 mysql_mutex_lock(&rli_ptr->data_lock);
6538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 354 times.
354 if (error) {
6539 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
6540 "Error in Xid_log_event: Commit could not be completed, '%s'",
6541 thd->get_stmt_da()->message_text());
6542 } else {
6543
2/8
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 354 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
354 DBUG_EXECUTE_IF(
6544 "crash_after_commit_before_update_pos",
6545 sql_print_information("Crashing "
6546 "crash_after_commit_before_update_pos.");
6547 DBUG_SUICIDE(););
6548 /* Update positions on successful commit */
6549
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 rli_ptr->set_group_master_log_name(new_group_master_log_name);
6550 354 rli_ptr->set_group_master_log_pos(new_group_master_log_pos);
6551
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 rli_ptr->notify_group_master_log_name_update();
6552
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 rli_ptr->set_group_relay_log_name(new_group_relay_log_name);
6553 354 rli_ptr->set_group_relay_log_pos(new_group_relay_log_pos);
6554
6555
3/8
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 354 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 354 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
354 DBUG_PRINT("info", ("Updating positions on succesful commit to group master"
6556 " %s %llu group relay %s %llu\n",
6557 rli_ptr->get_group_master_log_name(),
6558 rli_ptr->get_group_master_log_pos(),
6559 rli_ptr->get_group_relay_log_name(),
6560 rli_ptr->get_group_relay_log_pos()));
6561
6562 /*
6563 For transactional repository the positions are flushed ahead of commit.
6564 Where as for non transactional rli repository the positions are flushed
6565 only on successful commit.
6566 */
6567
6/8
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 353 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 353 times.
✓ Branch 7 taken 1 times.
354 if (!rli_ptr->is_transactional() && !already_logged_transaction)
6568
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli_ptr->flush_info(Relay_log_info::RLI_FLUSH_NO_OPTION);
6569 }
6570 353 err:
6571 // This is Bug#24588741 fix:
6572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 354 times.
354 if (rli_ptr->is_group_master_log_pos_invalid)
6573 rli_ptr->is_group_master_log_pos_invalid = false;
6574
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 mysql_cond_broadcast(&rli_ptr->data_cond);
6575
1/2
✓ Branch 0 taken 354 times.
✗ Branch 1 not taken.
354 mysql_mutex_unlock(&rli_ptr->data_lock);
6576
6577 354 return error;
6578 354 }
6579
6580 151079 Log_event::enum_skip_reason Xid_apply_log_event::do_shall_skip(
6581 Relay_log_info *rli) {
6582
1/2
✓ Branch 0 taken 151079 times.
✗ Branch 1 not taken.
151079 DBUG_TRACE;
6583
2/2
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 150801 times.
151079 if (rli->slave_skip_counter > 0) {
6584 278 thd->variables.option_bits &= ~OPTION_BEGIN;
6585 278 return Log_event::EVENT_SKIP_COUNT;
6586 }
6587
1/2
✓ Branch 0 taken 150802 times.
✗ Branch 1 not taken.
150801 return Log_event::do_shall_skip(rli);
6588 151080 }
6589
6590 /**************************************************************************
6591 XA_prepare_log_event methods
6592 **************************************************************************/
6593
6594 100 int XA_prepare_log_event::pack_info(Protocol *protocol) {
6595 char buf[ser_buf_size];
6596 char query[sizeof("XA COMMIT ONE PHASE") + 1 + sizeof(buf)];
6597
6598 /* RHS of the following assert is unknown to client sources */
6599 static_assert(ser_buf_size == XID::ser_buf_size, "");
6600 100 serialize_xid(buf, my_xid.formatID, my_xid.gtrid_length, my_xid.bqual_length,
6601 100 my_xid.data);
6602
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 69 times.
100 sprintf(query, (one_phase ? "XA COMMIT %s ONE PHASE" : "XA PREPARE %s"), buf);
6603
6604
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 protocol->store_string(query, strlen(query), &my_charset_bin);
6605 100 return 0;
6606 }
6607
6608 638 bool XA_prepare_log_event::write(Basic_ostream *ostream) {
6609 638 uint8 one_byte = one_phase;
6610 uchar buf_f[4];
6611 uchar buf_g[4];
6612 uchar buf_b[4];
6613 638 int4store(buf_f, static_cast<XID *>(xid)->get_format_id());
6614 638 int4store(buf_g, static_cast<XID *>(xid)->get_gtrid_length());
6615 638 int4store(buf_b, static_cast<XID *>(xid)->get_bqual_length());
6616
6617 assert(xid_bufs_size == sizeof(buf_f) + sizeof(buf_g) + sizeof(buf_b));
6618
6619 1914 return write_header(ostream,
6620 sizeof(one_byte) + xid_bufs_size +
6621
1/2
✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
1276 static_cast<XID *>(xid)->get_gtrid_length() +
6622 638 static_cast<XID *>(xid)->get_bqual_length()) ||
6623
2/4
✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 638 times.
✗ Branch 3 not taken.
638 wrapper_my_b_safe_write(ostream, &one_byte, sizeof(one_byte)) ||
6624
2/4
✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 638 times.
✗ Branch 3 not taken.
638 wrapper_my_b_safe_write(ostream, buf_f, sizeof(buf_f)) ||
6625
2/4
✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 638 times.
✗ Branch 3 not taken.
638 wrapper_my_b_safe_write(ostream, buf_g, sizeof(buf_g)) ||
6626
2/4
✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 638 times.
✗ Branch 3 not taken.
638 wrapper_my_b_safe_write(ostream, buf_b, sizeof(buf_b)) ||
6627
2/4
✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 638 times.
✗ Branch 3 not taken.
638 wrapper_my_b_safe_write(
6628 ostream,
6629 638 pointer_cast<const uchar *>(static_cast<XID *>(xid)->get_data()),
6630 1276 static_cast<XID *>(xid)->get_gtrid_length() +
6631
1/2
✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
1914 static_cast<XID *>(xid)->get_bqual_length()) ||
6632
2/4
✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 638 times.
1276 write_footer(ostream);
6633 }
6634 #endif // MYSQL_SERVER
6635
6636 #ifndef MYSQL_SERVER
6637 5 void XA_prepare_log_event::print(FILE *,
6638 PRINT_EVENT_INFO *print_event_info) const {
6639 5 IO_CACHE *const head = &print_event_info->head_cache;
6640 char buf[ser_buf_size];
6641
6642
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 print_header(head, print_event_info, false);
6643 5 serialize_xid(buf, my_xid.formatID, my_xid.gtrid_length, my_xid.bqual_length,
6644 5 my_xid.data);
6645
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_b_printf(head, "\tXA PREPARE %s\n", buf);
6646
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_b_printf(
6647 5 head, one_phase ? "XA COMMIT %s ONE PHASE\n%s\n" : "XA PREPARE %s\n%s\n",
6648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 buf, print_event_info->delimiter);
6649 5 }
6650 #endif /* !MYSQL_SERVER */
6651
6652 #if defined(MYSQL_SERVER)
6653
6654 /**
6655 Differs from Xid_log_event::do_commit in that it carries out
6656 XA prepare (not the commit).
6657 It also can commit on one phase when the event's member @c one_phase
6658 set to true.
6659
6660 @param thd_arg a pointer to THD handle
6661 @return false as success and
6662 true as an error
6663 */
6664
6665 352 bool XA_prepare_log_event::do_commit(THD *thd_arg) {
6666
1/2
✓ Branch 0 taken 352 times.
✗ Branch 1 not taken.
352 enum_gtid_statement_status state = gtid_pre_statement_checks(thd_arg);
6667
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 16 times.
352 if (state == GTID_STATEMENT_EXECUTE) {
6668
3/4
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 333 times.
336 if (gtid_pre_statement_post_implicit_commit_checks(thd_arg))
6669 3 state = GTID_STATEMENT_CANCEL;
6670 }
6671
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 349 times.
352 if (state == GTID_STATEMENT_CANCEL) {
6672 3 uint error = thd_arg->get_stmt_da()->mysql_errno();
6673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(error != 0);
6674
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 thd_arg->rli_slave->report(ERROR_LEVEL, error,
6675 "Error executing XA PREPARE event: '%s'",
6676 thd_arg->get_stmt_da()->message_text());
6677 3 thd_arg->is_slave_error = true;
6678 3 return true;
6679
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 333 times.
349 } else if (state == GTID_STATEMENT_SKIP)
6680 16 return false;
6681
6682 333 bool error = false;
6683 333 xid_t xid;
6684 333 xid.set(my_xid.formatID, my_xid.data, my_xid.gtrid_length,
6685
1/2
✓ Branch 0 taken 333 times.
✗ Branch 1 not taken.
333 my_xid.data + my_xid.gtrid_length, my_xid.bqual_length);
6686
2/2
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 55 times.
333 if (!one_phase) {
6687 /*
6688 This is XA-prepare branch.
6689 */
6690 278 thd_arg->lex->sql_command = SQLCOM_XA_PREPARE;
6691
2/4
✓ Branch 0 taken 278 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 278 times.
✗ Branch 3 not taken.
278 thd_arg->lex->m_sql_cmd = new (thd_arg->mem_root) Sql_cmd_xa_prepare(&xid);
6692
1/2
✓ Branch 0 taken 277 times.
✗ Branch 1 not taken.
278 error = thd_arg->lex->m_sql_cmd->execute(thd_arg);
6693 } else {
6694 55 thd_arg->lex->sql_command = SQLCOM_XA_COMMIT;
6695 55 thd_arg->lex->m_sql_cmd =
6696
2/4
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
55 new (thd_arg->mem_root) Sql_cmd_xa_commit(&xid, XA_ONE_PHASE);
6697
1/2
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
55 error = thd_arg->lex->m_sql_cmd->execute(thd_arg);
6698 }
6699
6700
3/4
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 324 times.
✗ Branch 3 not taken.
331 if (!error) error = mysql_bin_log.gtid_end_transaction(thd_arg);
6701
6702 331 return error;
6703 }
6704
6705 /**************************************************************************
6706 User_var_log_event methods
6707 **************************************************************************/
6708
6709 65 int User_var_log_event::pack_info(Protocol *protocol) {
6710 65 char *buf = nullptr;
6711 char quoted_id[1 + FN_REFLEN * 2 + 2]; // quoted identifier
6712 size_t id_len =
6713
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 my_strmov_quoted_identifier(this->thd, quoted_id, name, name_len);
6714 65 quoted_id[id_len] = '\0';
6715 65 size_t val_offset = 2 + id_len;
6716 65 size_t event_len = val_offset;
6717
6718
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 64 times.
65 if (is_null) {
6719
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!(buf = (char *)my_malloc(key_memory_log_event, val_offset + 5,
6720 MYF(MY_WME))))
6721 return 1;
6722 1 my_stpcpy(buf + val_offset, "NULL");
6723 1 event_len = val_offset + 4;
6724 } else {
6725
4/5
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
64 switch (type) {
6726 1 case REAL_RESULT:
6727 double real_val;
6728 1 real_val = float8get(val);
6729 2 if (!(buf = (char *)my_malloc(key_memory_log_event,
6730
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1,
6731 MYF(MY_WME))))
6732 return 1;
6733 1 event_len +=
6734
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
6735 buf + val_offset, nullptr);
6736 1 break;
6737 56 case INT_RESULT:
6738
2/4
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 56 times.
56 if (!(buf = (char *)my_malloc(key_memory_log_event, val_offset + 22,
6739 MYF(MY_WME))))
6740 return 1;
6741
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
112 event_len = longlong10_to_str(
6742 56 uint8korr(val), buf + val_offset,
6743
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 52 times.
56 ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10)) -
6744 buf;
6745 56 break;
6746 1 case DECIMAL_RESULT: {
6747
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!(buf = (char *)my_malloc(key_memory_log_event,
6748 val_offset + DECIMAL_MAX_STR_LENGTH + 1,
6749 MYF(MY_WME))))
6750 return 1;
6751 String str(buf + val_offset, DECIMAL_MAX_STR_LENGTH + 1,
6752 1 &my_charset_bin);
6753 1 my_decimal dec;
6754 1 binary2my_decimal(E_DEC_FATAL_ERROR, (uchar *)(val + 2), &dec, val[0],
6755
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 val[1]);
6756
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_decimal2string(E_DEC_FATAL_ERROR, &dec, &str);
6757 1 event_len = str.length() + val_offset;
6758 1 break;
6759 1 }
6760 6 case STRING_RESULT:
6761 /* 15 is for 'COLLATE' and other chars */
6762 12 buf = (char *)my_malloc(
6763 key_memory_log_event,
6764
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 event_len + val_len * 2 + 1 + 2 * MY_CS_NAME_SIZE + 15,
6765 MYF(MY_WME));
6766 CHARSET_INFO *cs;
6767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!buf) return 1;
6768
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (!(cs = get_charset(charset_number, MYF(0)))) {
6769 my_stpcpy(buf + val_offset, "???");
6770 event_len += 3;
6771 } else {
6772
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 char *p = strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
6773
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 p = str_to_hex(p, val, val_len);
6774
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 p = strxmov(p, " COLLATE ", cs->m_coll_name, NullS);
6775 6 event_len = p - buf;
6776 }
6777 6 break;
6778 case ROW_RESULT:
6779 default:
6780 assert(false);
6781 return 1;
6782 }
6783 }
6784 65 buf[0] = '@';
6785 65 memcpy(buf + 1, quoted_id, id_len);
6786 65 buf[1 + id_len] = '=';
6787
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 protocol->store_string(buf, event_len, &my_charset_bin);
6788
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 my_free(buf);
6789 65 return 0;
6790 }
6791 #endif /* MYSQL_SERVER */
6792
6793 7059 User_var_log_event::User_var_log_event(
6794 7059 const char *buf, const Format_description_event *description_event)
6795 : binary_log::User_var_event(buf, description_event),
6796 27 Log_event(header(), footer())
6797 #ifdef MYSQL_SERVER
6798 ,
6799 7032 deferred(false),
6800
1/2
✓ Branch 0 taken 7032 times.
✗ Branch 1 not taken.
7032 query_id(0)
6801 #endif
6802 {
6803
1/2
✓ Branch 0 taken 7059 times.
✗ Branch 1 not taken.
7059 DBUG_TRACE;
6804 7059 }
6805
6806 #ifdef MYSQL_SERVER
6807 9109 bool User_var_log_event::write(Basic_ostream *ostream) {
6808 char buf[UV_NAME_LEN_SIZE];
6809 char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE +
6810 UV_VAL_LEN_SIZE];
6811 9109 uchar buf2[std::max(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos = buf2;
6812 9109 uint unsigned_len = 0;
6813 uint buf1_length;
6814 ulong event_length;
6815
6816 9109 int4store(buf, name_len);
6817
6818
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 9087 times.
9109 if ((buf1[0] = is_null)) {
6819 22 buf1_length = 1;
6820 22 val_len = 0; // Length of 'pos'
6821 } else {
6822 9087 buf1[1] = type;
6823 9087 int4store(buf1 + 2, charset_number);
6824
6825
4/5
✓ Branch 0 taken 2773 times.
✓ Branch 1 taken 790 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 5508 times.
✗ Branch 4 not taken.
9087 switch (type) {
6826 2773 case REAL_RESULT:
6827 2773 float8store(buf2, *(double *)val);
6828 2773 break;
6829 790 case INT_RESULT:
6830 790 int8store(buf2, *(longlong *)val);
6831 790 unsigned_len = 1;
6832 790 break;
6833 16 case DECIMAL_RESULT: {
6834 16 my_decimal *dec = (my_decimal *)val;
6835 16 dec->sanity_check();
6836 16 buf2[0] = (char)(dec->intg + dec->frac);
6837 16 buf2[1] = (char)dec->frac;
6838
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 decimal2bin(dec, buf2 + 2, buf2[0], buf2[1]);
6839
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 val_len = decimal_bin_size(buf2[0], buf2[1]) + 2;
6840 16 break;
6841 }
6842 5508 case STRING_RESULT:
6843 5508 pos = (uchar *)val;
6844 5508 break;
6845 case ROW_RESULT:
6846 default:
6847 assert(false);
6848 return false;
6849 }
6850 9087 int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
6851 9087 buf1_length = 10;
6852 }
6853
6854 9109 event_length = sizeof(buf) + name_len + buf1_length + val_len + unsigned_len;
6855
6856
1/2
✓ Branch 0 taken 9109 times.
✗ Branch 1 not taken.
9109 return (write_header(ostream, event_length) ||
6857
2/4
✓ Branch 0 taken 9109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9109 times.
✗ Branch 3 not taken.
9109 wrapper_my_b_safe_write(ostream, (uchar *)buf, sizeof(buf)) ||
6858
2/4
✓ Branch 0 taken 9109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9109 times.
✗ Branch 3 not taken.
9109 wrapper_my_b_safe_write(ostream, pointer_cast<const uchar *>(name),
6859 9109 name_len) ||
6860
2/4
✓ Branch 0 taken 9109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9109 times.
✗ Branch 3 not taken.
9109 wrapper_my_b_safe_write(ostream, (uchar *)buf1, buf1_length) ||
6861
2/4
✓ Branch 0 taken 9109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9109 times.
✗ Branch 3 not taken.
9109 wrapper_my_b_safe_write(ostream, pos, val_len) ||
6862
3/6
✓ Branch 0 taken 9109 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9109 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9109 times.
✗ Branch 5 not taken.
27327 wrapper_my_b_safe_write(ostream, &flags, unsigned_len) ||
6863
2/4
✓ Branch 0 taken 9109 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9109 times.
18218 write_footer(ostream));
6864 }
6865 #endif
6866
6867 /*
6868 User_var_log_event::print()
6869 */
6870
6871 #ifndef MYSQL_SERVER
6872 24 void User_var_log_event::print(FILE *,
6873 PRINT_EVENT_INFO *print_event_info) const {
6874 24 IO_CACHE *const head = &print_event_info->head_cache;
6875 char quoted_id[1 + NAME_LEN * 2 + 2]; // quoted length of the identifier
6876 char name_id[NAME_LEN + 1];
6877 24 size_t quoted_len = 0;
6878
6879
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 15 times.
24 if (!print_event_info->short_form) {
6880
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 print_header(head, print_event_info, false);
6881
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_b_printf(head, "\tUser_var\n");
6882 }
6883 24 my_stpcpy(name_id, name);
6884 24 name_id[name_len] = '\0';
6885
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 my_b_printf(head, "SET @");
6886 quoted_len =
6887
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 my_strmov_quoted_identifier((char *)quoted_id, (const char *)name_id);
6888 24 quoted_id[quoted_len] = '\0';
6889 [[maybe_unused]]
6890
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 int write_res = my_b_write(head, (uchar *)quoted_id, quoted_len);
6891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 assert(write_res == 0);
6892
6893
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 23 times.
24 if (is_null) {
6894
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_b_printf(head, ":=NULL%s\n", print_event_info->delimiter);
6895 } else {
6896
4/5
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
23 switch (type) {
6897 2 case REAL_RESULT:
6898 double real_val;
6899 char real_buf[FMT_G_BUFSIZE(14)];
6900 2 real_val = float8get(val);
6901 2 sprintf(real_buf, "%.14g", real_val);
6902
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_b_printf(head, ":=%s%s\n", real_buf, print_event_info->delimiter);
6903 23 break;
6904 9 case INT_RESULT:
6905 char int_buf[22];
6906
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
18 longlong10_to_str(
6907 9 uint8korr(val), int_buf,
6908
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10));
6909
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_b_printf(head, ":=%s%s\n", int_buf, print_event_info->delimiter);
6910 9 break;
6911 2 case DECIMAL_RESULT: {
6912 char str_buf[DECIMAL_MAX_STR_LENGTH + 1];
6913 2 int str_len = sizeof(str_buf);
6914 2 int precision = (int)val[0];
6915 2 int scale = (int)val[1];
6916 decimal_digit_t dec_buf[10];
6917 decimal_t dec;
6918 2 dec.len = 10;
6919 2 dec.buf = dec_buf;
6920
6921
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 bin2decimal((uchar *)val + 2, &dec, precision, scale);
6922
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 decimal2string(&dec, str_buf, &str_len);
6923
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_b_printf(head, ":=%s%s\n", str_buf, print_event_info->delimiter);
6924 2 break;
6925 }
6926 10 case STRING_RESULT: {
6927 /*
6928 Let's express the string in hex. That's the most robust way. If we
6929 print it in character form instead, we need to escape it with
6930 character_set_client which we don't know (we will know it in 5.0, but
6931 in 4.1 we don't know it easily when we are printing
6932 User_var_log_event). Explanation why we would need to bother with
6933 character_set_client (quoting Bar):
6934 > Note, the parser doesn't switch to another unescaping mode after
6935 > it has met a character set introducer.
6936 > For example, if an SJIS client says something like:
6937 > SET @a= _ucs2 \0a\0b'
6938 > the string constant is still unescaped according to SJIS, not
6939 > according to UCS2.
6940 */
6941 char *hex_str;
6942 CHARSET_INFO *cs;
6943
6944
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 hex_str = (char *)my_malloc(key_memory_log_event, 2 * val_len + 1 + 2,
6945 MYF(MY_WME)); // 2 hex digits / byte
6946
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (!hex_str) return;
6947
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 str_to_hex(hex_str, val, val_len);
6948 /*
6949 For proper behaviour when mysqlbinlog|mysql, we need to explicitly
6950 specify the variable's collation. It will however cause problems when
6951 people want to mysqlbinlog|mysql into another server not supporting
6952 the character set. But there's not much to do about this and it's
6953 unlikely.
6954 */
6955
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 if (!(cs = get_charset(charset_number, MYF(0))))
6956 /*
6957 Generate an unusable command (=> syntax error) is probably the best
6958 thing we can do here.
6959 */
6960 my_b_printf(head, ":=???%s\n", print_event_info->delimiter);
6961 else
6962 10 my_b_printf(head, ":=_%s %s COLLATE `%s`%s\n", cs->csname, hex_str,
6963
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 cs->m_coll_name, print_event_info->delimiter);
6964
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 my_free(hex_str);
6965 10 } break;
6966 case ROW_RESULT:
6967 default:
6968 assert(false);
6969 return;
6970 }
6971 }
6972 }
6973 #endif
6974
6975 /*
6976 User_var_log_event::do_apply_event()
6977 */
6978
6979 #if defined(MYSQL_SERVER)
6980 6909 int User_var_log_event::do_apply_event(Relay_log_info const *rli) {
6981
1/2
✓ Branch 0 taken 6909 times.
✗ Branch 1 not taken.
6909 DBUG_TRACE;
6982 6909 Item *it = nullptr;
6983 CHARSET_INFO *charset;
6984 6909 query_id_t sav_query_id = 0; /* memorize orig id when deferred applying */
6985
6986
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6908 times.
6909 if (rli->deferred_events_collecting) {
6987
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 set_deferred(current_thd->query_id);
6988
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 int ret = rli->deferred_events->add(this);
6989 1 return ret;
6990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6908 times.
6908 } else if (is_deferred()) {
6991 sav_query_id = current_thd->query_id;
6992 current_thd->query_id = query_id; /* recreating original time context */
6993 }
6994
6995
2/4
✓ Branch 0 taken 6908 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6908 times.
6908 if (!(charset = get_charset(charset_number, MYF(MY_WME)))) {
6996 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6997 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6998 "Invalid character set for User var event");
6999 return 1;
7000 }
7001 double real_val;
7002 longlong int_val;
7003
7004 /*
7005 We are now in a statement until the associated query log event has
7006 been processed.
7007 */
7008 6908 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
7009
7010
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6898 times.
6908 if (is_null) {
7011
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
20 it = new Item_null();
7012 } else {
7013
4/5
✓ Branch 0 taken 1871 times.
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 4781 times.
✗ Branch 4 not taken.
6898 switch (type) {
7014 1871 case REAL_RESULT:
7015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1871 times.
1871 if (val_len != 8) {
7016 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7017 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7018 "Invalid variable length at User var event");
7019 return 1;
7020 }
7021 1871 real_val = float8get(val);
7022
2/4
✓ Branch 0 taken 1871 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1871 times.
✗ Branch 3 not taken.
1871 it = new Item_float(real_val, 0);
7023 1871 val = (char *)&real_val; // Pointer to value in native format
7024 1871 val_len = 8;
7025 1871 break;
7026 239 case INT_RESULT:
7027
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 239 times.
239 if (val_len != 8) {
7028 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7029 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7030 "Invalid variable length at User var event");
7031 return 1;
7032 }
7033 239 int_val = (longlong)uint8korr(val);
7034
2/4
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
✗ Branch 3 not taken.
239 it = new Item_int(int_val);
7035 239 val = (char *)&int_val; // Pointer to value in native format
7036 239 val_len = 8;
7037 239 break;
7038 7 case DECIMAL_RESULT: {
7039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (val_len < 3) {
7040 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7041 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
7042 "Invalid variable length at User var event");
7043 return 1;
7044 }
7045
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 Item_decimal *dec = new Item_decimal((uchar *)val + 2, val[0], val[1]);
7046 7 it = dec;
7047
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 val = (char *)dec->val_decimal(nullptr);
7048 7 val_len = sizeof(my_decimal);
7049 7 break;
7050 }
7051 4781 case STRING_RESULT:
7052
2/4
✓ Branch 0 taken 4781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4781 times.
✗ Branch 3 not taken.
4781 it = new Item_string(val, val_len, charset);
7053 4781 break;
7054 case ROW_RESULT:
7055 default:
7056 assert(false);
7057 return 0;
7058 }
7059 }
7060 Item_func_set_user_var *e =
7061
3/6
✓ Branch 0 taken 6908 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6908 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6908 times.
✗ Branch 5 not taken.
6908 new Item_func_set_user_var(Name_string(name, name_len, false), it);
7062 /*
7063 Item_func_set_user_var can't substitute something else on its place =>
7064 0 can be passed as last argument (reference on item)
7065
7066 Fix_fields() can fail, in which case a call of update_hash() might
7067 crash the server, so if fix fields fails, we just return with an
7068 error.
7069 */
7070
2/4
✓ Branch 0 taken 6908 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6908 times.
6908 if (e->fix_fields(thd, nullptr)) return 1;
7071
7072
2/4
✓ Branch 0 taken 6908 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6908 times.
6908 if (e->set_entry(thd, true)) return 1;
7073
7074 /*
7075 A variable can just be considered as a table with
7076 a single record and with a single column. Thus, like
7077 a column value, it could always have IMPLICIT derivation.
7078 */
7079 6908 e->update_hash(val, val_len, (Item_result)type, charset, DERIVATION_IMPLICIT,
7080
1/2
✓ Branch 0 taken 6908 times.
✗ Branch 1 not taken.
6908 (flags & binary_log::User_var_event::UNSIGNED_F));
7081
1/2
✓ Branch 0 taken 6908 times.
✗ Branch 1 not taken.
6908 if (!is_deferred())
7082
1/2
✓ Branch 0 taken 6908 times.
✗ Branch 1 not taken.
6908 thd->mem_root->Clear();
7083 else
7084 current_thd->query_id = sav_query_id; /* restore current query's context */
7085
7086 6908 return 0;
7087 6909 }
7088
7089 3 int User_var_log_event::do_update_pos(Relay_log_info *rli) {
7090 3 rli->inc_event_relay_log_pos();
7091 3 return 0;
7092 }
7093
7094 6905 Log_event::enum_skip_reason User_var_log_event::do_shall_skip(
7095 Relay_log_info *rli) {
7096 /*
7097 It is a common error to set the slave skip counter to 1 instead
7098 of 2 when recovering from an insert which used a auto increment,
7099 rand, or user var. Therefore, if the slave skip counter is 1, we
7100 just say that this event should be skipped by ignoring it, meaning
7101 that we do not change the value of the slave skip counter since it
7102 will be decreased by the following insert event.
7103 */
7104 6905 return continue_group(rli);
7105 }
7106 #endif /* MYSQL_SERVER */
7107
7108 /**************************************************************************
7109 Unknown_log_event methods
7110 **************************************************************************/
7111
7112 #ifndef MYSQL_SERVER
7113 69 void Unknown_log_event::print(FILE *,
7114 PRINT_EVENT_INFO *print_event_info) const {
7115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (print_event_info->short_form) return;
7116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 if (what != kind::ENCRYPTED_WITH_5_7) {
7117 print_header(&print_event_info->head_cache, print_event_info, false);
7118 my_b_printf(&print_event_info->head_cache, "\n# %s", "Unknown event\n");
7119 } else
7120 69 my_b_printf(&print_event_info->head_cache, "\n# %s",
7121 "Event encrypted with 5.7 Percona Server binlog encryption\n");
7122 }
7123
7124 /**************************************************************************
7125 Stop_log_event methods
7126 **************************************************************************/
7127
7128 /*
7129 Stop_log_event::print()
7130 */
7131
7132 11 void Stop_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
7133
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
11 if (print_event_info->short_form) return;
7134
7135 6 print_header(&print_event_info->head_cache, print_event_info, false);
7136 6 my_b_printf(&print_event_info->head_cache, "\tStop\n");
7137 }
7138 #endif /* !MYSQL_SERVER */
7139
7140 #ifdef MYSQL_SERVER
7141 /*
7142 The master stopped. We used to clean up all temporary tables but
7143 this is useless as, as the master has shut down properly, it has
7144 written all DROP TEMPORARY TABLE (prepared statements' deletion is
7145 TODO only when we binlog prep stmts). We used to clean up
7146 replica_load_tmpdir, but this is useless as it has been cleared at the
7147 end of LOAD DATA INFILE. So we have nothing to do here. The place
7148 were we must do this cleaning is in
7149 Start_log_event_v3::do_apply_event(), not here. Because if we come
7150 here, the master was sane.
7151
7152 This must only be called from the Slave SQL thread, since it calls
7153 flush_relay_log_info().
7154 */
7155 944 int Stop_log_event::do_update_pos(Relay_log_info *rli) {
7156 944 int error_inc = 0;
7157 944 int error_flush = 0;
7158 /*
7159 We do not want to update master_log pos because we get a rotate event
7160 before stop, so by now group_master_log_name is set to the next log.
7161 If we updated it, we will have incorrect master coordinates and this
7162 could give false triggers in SOURCE_POS_WAIT() that we have reached
7163 the target position when in fact we have not.
7164 The group position is always unchanged in MTS mode because the event
7165 is never executed so can't be scheduled to a Worker.
7166 */
7167
5/6
✓ Branch 0 taken 944 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 940 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 940 times.
✓ Branch 5 taken 4 times.
944 if ((thd->variables.option_bits & OPTION_BEGIN) || rli->is_parallel_exec())
7168 940 rli->inc_event_relay_log_pos();
7169 else {
7170 4 error_inc = rli->inc_group_relay_log_pos(0, true /*need_data_lock=true*/);
7171 4 error_flush = rli->flush_info(Relay_log_info::RLI_FLUSH_IGNORE_SYNC_OPT);
7172 }
7173
2/4
✓ Branch 0 taken 944 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 944 times.
944 return (error_inc || error_flush);
7174 }
7175
7176 /**************************************************************************
7177 Append_block_log_event methods
7178 **************************************************************************/
7179
7180 /*
7181 Append_block_log_event ctor
7182 */
7183
7184 8240 Append_block_log_event::Append_block_log_event(THD *thd_arg, const char *db_arg,
7185 uchar *block_arg,
7186 uint block_len_arg,
7187 186 bool using_trans)
7188 : binary_log::Append_block_event(db_arg, block_arg, block_len_arg,
7189 thd_arg->file_id),
7190 Log_event(thd_arg, 0,
7191 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
7192 : Log_event::EVENT_STMT_CACHE,
7193
3/5
✓ Branch 0 taken 3498 times.
✓ Branch 1 taken 622 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 93 times.
✗ Branch 4 not taken.
8240 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
7194 8240 common_header->set_is_valid(block != nullptr);
7195 8240 }
7196 #endif // MYSQL_SERVER
7197
7198 /*
7199 Append_block_log_event ctor
7200 */
7201
7202 386 Append_block_log_event::Append_block_log_event(
7203 16 const char *buf, const Format_description_event *description_event)
7204 : binary_log::Append_block_event(buf, description_event),
7205
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
386 Log_event(header(), footer()) {
7206
1/2
✓ Branch 0 taken 193 times.
✗ Branch 1 not taken.
386 DBUG_TRACE;
7207 386 }
7208
7209 /*
7210 Append_block_log_event::write()
7211 */
7212
7213 #ifdef MYSQL_SERVER
7214 232 bool Append_block_log_event::write(Basic_ostream *ostream) {
7215 uchar buf[Binary_log_event::APPEND_BLOCK_HEADER_LEN];
7216 232 int4store(buf + AB_FILE_ID_OFFSET, file_id);
7217 464 return (write_header(ostream,
7218
1/2
✓ Branch 0 taken 232 times.
✗ Branch 1 not taken.
232 Binary_log_event::APPEND_BLOCK_HEADER_LEN + block_len) ||
7219
2/4
✓ Branch 0 taken 232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 232 times.
✗ Branch 3 not taken.
232 wrapper_my_b_safe_write(ostream, buf,
7220 232 Binary_log_event::APPEND_BLOCK_HEADER_LEN) ||
7221
3/6
✓ Branch 0 taken 232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 232 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 232 times.
✗ Branch 5 not taken.
696 wrapper_my_b_safe_write(ostream, block, block_len) ||
7222
2/4
✓ Branch 0 taken 232 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 232 times.
464 write_footer(ostream));
7223 }
7224 #endif
7225
7226 /*
7227 Append_block_log_event::print()
7228 */
7229
7230 #ifndef MYSQL_SERVER
7231 50 void Append_block_log_event::print(FILE *,
7232 PRINT_EVENT_INFO *print_event_info) const {
7233
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 23 times.
50 if (print_event_info->short_form) return;
7234 23 print_header(&print_event_info->head_cache, print_event_info, false);
7235 23 my_b_printf(&print_event_info->head_cache,
7236 23 "\n#%s: file_id: %d block_len: %d\n", get_type_str(), file_id,
7237 23 block_len);
7238 }
7239 #endif /* !MYSQL_SERVER */
7240
7241 /*
7242 Append_block_log_event::pack_info()
7243 */
7244
7245 #if defined(MYSQL_SERVER)
7246 18 int Append_block_log_event::pack_info(Protocol *protocol) {
7247 char buf[256];
7248 size_t length;
7249 18 length = snprintf(buf, sizeof(buf), ";file_id=%u;block_len=%u", file_id,
7250 block_len);
7251
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 protocol->store_string(buf, length, &my_charset_bin);
7252 18 return 0;
7253 }
7254
7255 /*
7256 Append_block_log_event::get_create_or_append()
7257 */
7258
7259 4 int Append_block_log_event::get_create_or_append() const {
7260 4 return 0; /* append to the file, fail if not exists */
7261 }
7262
7263 /*
7264 Append_block_log_event::do_apply_event()
7265 */
7266
7267 100 int Append_block_log_event::do_apply_event(Relay_log_info const *rli) {
7268 char fname[FN_REFLEN + TEMP_FILE_MAX_LEN];
7269 int fd;
7270 100 int error = 1;
7271
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 DBUG_TRACE;
7272
7273
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 Applier_security_context_guard security_context{rli, thd};
7274
3/4
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
✓ Branch 3 taken 2 times.
100 if (DBUG_EVALUATE_IF("skip_the_priv_check_in_begin_load", false, true)) {
7275
3/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 92 times.
98 if (!security_context.skip_priv_checks()) {
7276
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 if (!security_context.has_access({FILE_ACL})) {
7277
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report_privilege_check_error(
7278 ERROR_LEVEL,
7279 Relay_log_info::enum_priv_checks_status::
7280 LOAD_DATA_EVENT_NOT_ALLOWED,
7281 false /* to client */);
7282 2 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7283 }
7284 }
7285 }
7286 #ifndef NDEBUG
7287 else { // Let's ensure that we actually skipped the privilege check since the
7288 // error code caugth in test scripts would be the same as the no-skip
7289 // case. Test scripts should wait on the below signal, if
7290 // `skip_the_priv_check_in_begin_load` has been set.
7291 2 const char act[] = "now SIGNAL skipped_the_priv_check_in_begin_load";
7292
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
7293 }
7294 #endif
7295
7296
1/2
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
98 THD_STAGE_INFO(thd, stage_making_temp_file_append_before_load_data);
7297
1/2
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
98 slave_load_file_stem(fname, file_id, server_id, ".data");
7298
3/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 4 times.
98 if (get_create_or_append()) {
7299 /*
7300 Usually lex_start() is called by dispatch_sql_command(), but we need it
7301 here as the present method does not call dispatch_sql_command().
7302 */
7303
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 lex_start(thd);
7304
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 mysql_reset_thd_for_next_command(thd);
7305 /* old copy may exist already */
7306
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 mysql_file_delete(key_file_log_event_data, fname, MYF(0));
7307
2/4
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 94 times.
94 DBUG_EXECUTE_IF("simulate_file_create_error_Append_block_event",
7308 { strcat(fname, "/"); });
7309
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 if ((fd = mysql_file_create(key_file_log_event_data, fname, CREATE_MODE,
7310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 O_WRONLY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) <
7311 0) {
7312 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7313 "Error in %s event: could not create file '%s', '%s'",
7314 get_type_str(), fname, thd->get_stmt_da()->message_text());
7315 goto err;
7316 }
7317
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 } else if ((fd = mysql_file_open(key_file_log_event_data, fname,
7318 O_WRONLY | O_APPEND | O_NOFOLLOW,
7319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 MYF(MY_WME))) < 0) {
7320 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7321 "Error in %s event: could not open file '%s', '%s'",
7322 get_type_str(), fname, thd->get_stmt_da()->message_text());
7323 goto err;
7324 }
7325
4/6
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 97 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
98 DBUG_EXECUTE_IF("remove_replica_load_file_before_write",
7326 { my_delete_allow_opened(fname, MYF(0)); });
7327
7328
2/6
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 98 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
98 DBUG_EXECUTE_IF("simulate_file_write_error_Append_block_event",
7329 { mysql_file_close(fd, MYF(0)); });
7330
2/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 98 times.
98 if (mysql_file_write(fd, block, block_len, MYF(MY_WME + MY_NABP))) {
7331 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7332 "Error in %s event: write to '%s' failed, '%s'", get_type_str(),
7333 fname, thd->get_stmt_da()->message_text());
7334 goto err;
7335 }
7336 98 error = 0;
7337
7338 98 err:
7339
2/4
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
98 if (fd >= 0) mysql_file_close(fd, MYF(0));
7340 98 return error;
7341 100 }
7342
7343 /**************************************************************************
7344 Delete_file_log_event methods
7345 **************************************************************************/
7346
7347 /*
7348 Delete_file_log_event ctor
7349 */
7350
7351 11 Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char *db_arg,
7352 11 bool using_trans)
7353 : binary_log::Delete_file_event(thd_arg->file_id, db_arg),
7354 Log_event(thd_arg, 0,
7355 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
7356 : Log_event::EVENT_STMT_CACHE,
7357
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
7358 11 common_header->set_is_valid(file_id != 0);
7359 11 }
7360 #endif // MYSQL_SERVER
7361
7362 /*
7363 Delete_file_log_event ctor
7364 */
7365
7366 5 Delete_file_log_event::Delete_file_log_event(
7367 5 const char *buf, const Format_description_event *description_event)
7368 : binary_log::Delete_file_event(buf, description_event),
7369
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 Log_event(header(), footer()) {
7370
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 DBUG_TRACE;
7371 5 }
7372
7373 /*
7374 Delete_file_log_event::write()
7375 */
7376
7377 #ifdef MYSQL_SERVER
7378 11 bool Delete_file_log_event::write(Basic_ostream *ostream) {
7379 uchar buf[Binary_log_event::DELETE_FILE_HEADER_LEN];
7380 11 int4store(buf + DF_FILE_ID_OFFSET, file_id);
7381
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 return (write_header(ostream, sizeof(buf)) ||
7382
3/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
22 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
7383
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
22 write_footer(ostream));
7384 }
7385 #endif
7386
7387 /*
7388 Delete_file_log_event::print()
7389 */
7390
7391 #ifndef MYSQL_SERVER
7392 void Delete_file_log_event::print(FILE *,
7393 PRINT_EVENT_INFO *print_event_info) const {
7394 if (print_event_info->short_form) return;
7395 print_header(&print_event_info->head_cache, print_event_info, false);
7396 my_b_printf(&print_event_info->head_cache, "\n#Delete_file: file_id=%u\n",
7397 file_id);
7398 }
7399 #endif /* !MYSQL_SERVER */
7400
7401 /*
7402 Delete_file_log_event::pack_info()
7403 */
7404
7405 #if defined(MYSQL_SERVER)
7406 int Delete_file_log_event::pack_info(Protocol *protocol) {
7407 char buf[64];
7408 size_t length;
7409 length = snprintf(buf, sizeof(buf), ";file_id=%u", (uint)file_id);
7410 protocol->store_string(buf, length, &my_charset_bin);
7411 return 0;
7412 }
7413
7414 /*
7415 Delete_file_log_event::do_apply_event()
7416 */
7417
7418 4 int Delete_file_log_event::do_apply_event(Relay_log_info const *rli) {
7419 char fname[FN_REFLEN + TEMP_FILE_MAX_LEN];
7420
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 lex_start(thd);
7421
7422
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 Applier_security_context_guard security_context{rli, thd};
7423
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
4 if (!security_context.skip_priv_checks()) {
7424
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (!security_context.has_access({FILE_ACL})) {
7425
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report_privilege_check_error(
7426 ERROR_LEVEL,
7427 Relay_log_info::enum_priv_checks_status::LOAD_DATA_EVENT_NOT_ALLOWED,
7428 false /* to client */);
7429 1 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7430 }
7431 }
7432
7433
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_reset_thd_for_next_command(thd);
7434
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 char *ext = slave_load_file_stem(fname, file_id, server_id, ".data");
7435
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
7436 3 my_stpcpy(ext, ".info");
7437
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME));
7438 3 return 0;
7439 4 }
7440
7441 /**************************************************************************
7442 Begin_load_query_log_event methods
7443 **************************************************************************/
7444
7445 8054 Begin_load_query_log_event::Begin_load_query_log_event(THD *thd_arg,
7446 const char *db_arg,
7447 uchar *block_arg,
7448 uint block_len_arg,
7449 8054 bool using_trans)
7450 : binary_log::Append_block_event(db_arg, block_arg, block_len_arg,
7451 thd_arg->file_id),
7452 Append_block_log_event(thd_arg, db_arg, block_arg, block_len_arg,
7453 using_trans),
7454
1/2
✓ Branch 0 taken 4027 times.
✗ Branch 1 not taken.
8054 binary_log::Begin_load_query_event() {
7455 8054 common_header->type_code = binary_log::BEGIN_LOAD_QUERY_EVENT;
7456
1/2
✓ Branch 0 taken 4027 times.
✗ Branch 1 not taken.
8054 file_id = thd_arg->file_id = mysql_bin_log.next_file_id();
7457 }
7458 #endif // MYSQL_SERVER
7459
7460 370 Begin_load_query_log_event::Begin_load_query_log_event(
7461 370 const char *buf, const Format_description_event *desc_event)
7462 : binary_log::Append_block_event(buf, desc_event),
7463 Append_block_log_event(buf, desc_event),
7464
2/4
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 185 times.
✗ Branch 3 not taken.
370 binary_log::Begin_load_query_event(buf, desc_event) {
7465
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
370 DBUG_TRACE;
7466 }
7467
7468 #if defined(MYSQL_SERVER)
7469 94 int Begin_load_query_log_event::get_create_or_append() const {
7470 94 return 1; /* create the file */
7471 }
7472
7473 102 Log_event::enum_skip_reason Begin_load_query_log_event::do_shall_skip(
7474 Relay_log_info *rli) {
7475 /*
7476 If the slave skip counter is 1, then we should not start executing
7477 on the next event.
7478 */
7479 102 return continue_group(rli);
7480 }
7481
7482 /**************************************************************************
7483 Execute_load_query_log_event methods
7484 **************************************************************************/
7485
7486 8032 Execute_load_query_log_event::Execute_load_query_log_event(
7487 THD *thd_arg, const char *query_arg, ulong query_length_arg,
7488 uint fn_pos_start_arg, uint fn_pos_end_arg,
7489 binary_log::enum_load_dup_handling dup_handling_arg, bool using_trans,
7490 8032 bool immediate, bool suppress_use, int errcode)
7491 : binary_log::Query_event(
7492 8032 query_arg, thd_arg->catalog().str, thd_arg->db().str,
7493 8032 query_length_arg, thd_arg->thread_id(), thd_arg->variables.sql_mode,
7494 thd_arg->variables.auto_increment_increment,
7495 thd_arg->variables.auto_increment_offset,
7496 8032 thd_arg->variables.lc_time_names->number,
7497 8032 (ulonglong)thd_arg->table_map_for_update, errcode),
7498 Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
7499 immediate, suppress_use, errcode),
7500 binary_log::Execute_load_query_event(thd_arg->file_id, fn_pos_start_arg,
7501
2/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 4016 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4016 times.
✗ Branch 5 not taken.
16064 fn_pos_end_arg, dup_handling_arg) {
7502
3/6
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4016 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4016 times.
✗ Branch 5 not taken.
8032 common_header->set_is_valid(Query_log_event::is_valid() && file_id != 0);
7503 8032 common_header->type_code = binary_log::EXECUTE_LOAD_QUERY_EVENT;
7504 }
7505 #endif /* MYSQL_SERVER */
7506
7507 352 Execute_load_query_log_event::Execute_load_query_log_event(
7508 352 const char *buf, const Format_description_event *desc_event)
7509 : binary_log::Query_event(buf, desc_event,
7510 binary_log::EXECUTE_LOAD_QUERY_EVENT),
7511 Query_log_event(buf, desc_event, binary_log::EXECUTE_LOAD_QUERY_EVENT),
7512
2/4
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 176 times.
✗ Branch 3 not taken.
352 binary_log::Execute_load_query_event(buf, desc_event) {
7513
1/2
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
352 DBUG_TRACE;
7514
3/4
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 128 times.
352 if (!is_valid()) return;
7515
3/4
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 128 times.
352 if (!Query_log_event::is_valid()) {
7516 // clear all the variables set in execute_load_query_event
7517 file_id = 0;
7518 fn_pos_start = 0;
7519 fn_pos_end = 0;
7520 dup_handling = binary_log::LOAD_DUP_ERROR;
7521 }
7522
3/6
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 176 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 128 times.
✗ Branch 5 not taken.
352 common_header->set_is_valid(Query_log_event::is_valid() && file_id != 0);
7523 }
7524
7525 214 ulong Execute_load_query_log_event::get_post_header_size_for_derived() {
7526 214 return Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN;
7527 }
7528
7529 #ifdef MYSQL_SERVER
7530 214 bool Execute_load_query_log_event::write_post_header_for_derived(
7531 Basic_ostream *ostream) {
7532 uchar buf[Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN];
7533 214 int4store(buf, file_id);
7534 214 int4store(buf + 4, fn_pos_start);
7535 214 int4store(buf + 4 + 4, fn_pos_end);
7536 214 *(buf + 4 + 4 + 4) = (uchar)dup_handling;
7537
7538
1/2
✓ Branch 0 taken 214 times.
✗ Branch 1 not taken.
214 return wrapper_my_b_safe_write(
7539 428 ostream, buf, Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
7540 }
7541 #endif
7542
7543 #ifndef MYSQL_SERVER
7544 void Execute_load_query_log_event::print(
7545 FILE *file, PRINT_EVENT_INFO *print_event_info) const {
7546 print(file, print_event_info, nullptr);
7547 }
7548
7549 /**
7550 Prints the query as LOAD DATA LOCAL and with rewritten filename.
7551 */
7552 36 void Execute_load_query_log_event::print(FILE *,
7553 PRINT_EVENT_INFO *print_event_info,
7554 const char *local_fname) const {
7555 [[maybe_unused]] int write_res;
7556 36 IO_CACHE *const head = &print_event_info->head_cache;
7557
7558 36 print_query_header(head, print_event_info);
7559 /**
7560 reduce the size of io cache so that the write function is called
7561 for every call to my_b_printf().
7562 */
7563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 DBUG_EXECUTE_IF("simulate_execute_event_write_error", {
7564 head->write_pos = head->write_end;
7565 DBUG_SET("+d,simulate_file_write_error");
7566 });
7567
7568
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if (local_fname) {
7569 write_res =
7570 36 my_b_write(head, pointer_cast<const uchar *>(query), fn_pos_start);
7571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 assert(write_res == 0);
7572 36 my_b_printf(head, " LOCAL INFILE ");
7573 36 pretty_print_str(head, local_fname, strlen(local_fname));
7574
7575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (dup_handling == binary_log::LOAD_DUP_REPLACE)
7576 my_b_printf(head, " REPLACE");
7577 36 my_b_printf(head, " INTO");
7578 36 my_b_write(head, pointer_cast<const uchar *>(query) + fn_pos_end,
7579 36 q_len - fn_pos_end);
7580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 assert(write_res == 0);
7581 36 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
7582 } else {
7583 write_res = my_b_write(head, pointer_cast<const uchar *>(query), q_len);
7584 assert(write_res == 0);
7585 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
7586 }
7587
7588
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 21 times.
36 if (!print_event_info->short_form)
7589 15 my_b_printf(head, "# file_id: %d \n", file_id);
7590 36 }
7591 #endif
7592
7593 #if defined(MYSQL_SERVER)
7594 16 int Execute_load_query_log_event::pack_info(Protocol *protocol) {
7595 char *buf, *pos;
7596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!(buf = (char *)my_malloc(key_memory_log_event,
7597 16 9 + (db_len * 2) + 2 + q_len + 10 + 21,
7598 MYF(MY_WME))))
7599 return 1;
7600 16 pos = buf;
7601
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if (db && db_len) {
7602 /*
7603 Statically allocates room to store '\0' and an identifier
7604 that may have NAME_LEN * 2 due to quoting and there are
7605 two quoting characters that wrap them.
7606 */
7607 char quoted_db[1 + NAME_LEN * 2 + 2]; // quoted length of the identifier
7608 16 size_t size = 0;
7609
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 size = my_strmov_quoted_identifier(this->thd, quoted_db, db, 0);
7610 16 pos = my_stpcpy(buf, "use ");
7611 16 memcpy(pos, quoted_db, size);
7612 16 pos = my_stpcpy(pos + size, "; ");
7613 }
7614
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if (query && q_len) {
7615 16 memcpy(pos, query, q_len);
7616 16 pos += q_len;
7617 }
7618 16 pos = my_stpcpy(pos, " ;file_id=");
7619 16 pos = longlong10_to_str(file_id, pos, 10);
7620 16 protocol->store_string(buf, pos - buf, &my_charset_bin);
7621 16 my_free(buf);
7622 16 return 0;
7623 }
7624
7625 90 int Execute_load_query_log_event::do_apply_event(Relay_log_info const *rli) {
7626 char *p;
7627 char *buf;
7628 char *fname;
7629 char *fname_end;
7630 int error;
7631
7632
1/2
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
90 Applier_security_context_guard security_context{rli, thd};
7633
3/4
✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 87 times.
90 if (!security_context.skip_priv_checks()) {
7634
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (!security_context.has_access({FILE_ACL})) {
7635
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report_privilege_check_error(
7636 ERROR_LEVEL,
7637 Relay_log_info::enum_priv_checks_status::LOAD_DATA_EVENT_NOT_ALLOWED,
7638 false /* to client */);
7639 1 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7640 }
7641 }
7642
7643 178 buf = (char *)my_malloc(key_memory_log_event,
7644
1/2
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
89 q_len + 1 - (fn_pos_end - fn_pos_start) +
7645 (FN_REFLEN + TEMP_FILE_MAX_LEN) + 10 + 8 + 5,
7646 MYF(MY_WME));
7647
7648
4/6
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 88 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
89 DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", my_free(buf);
7649 buf = nullptr;);
7650
7651 /* Replace filename and LOCAL keyword in query before executing it */
7652
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 88 times.
89 if (buf == nullptr) {
7653
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7654
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_SLAVE_FATAL_ERROR), "Not enough memory");
7655 1 return 1;
7656 }
7657
7658 88 p = buf;
7659 88 memcpy(p, query, fn_pos_start);
7660 88 p += fn_pos_start;
7661
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 fname = (p = strmake(p, STRING_WITH_LEN(" INFILE \'")));
7662
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 p = slave_load_file_stem(p, file_id, server_id, ".data");
7663 88 fname_end = p = strend(p); // Safer than p=p+5
7664 88 *(p++) = '\'';
7665
3/3
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 49 times.
88 switch (dup_handling) {
7666 35 case binary_log::LOAD_DUP_IGNORE:
7667
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 p = strmake(p, STRING_WITH_LEN(" IGNORE"));
7668 35 break;
7669 4 case binary_log::LOAD_DUP_REPLACE:
7670
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 p = strmake(p, STRING_WITH_LEN(" REPLACE"));
7671 4 break;
7672 49 default:
7673 /* Ordinary load data */
7674 49 break;
7675 }
7676
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 p = strmake(p, STRING_WITH_LEN(" INTO "));
7677
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 p = strmake(p, query + fn_pos_end, q_len - fn_pos_end);
7678
7679
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 error = Query_log_event::do_apply_event(rli, buf, p - buf);
7680
7681 /* Forging file name for deletion in same buffer */
7682 88 *fname_end = 0;
7683
7684 /*
7685 If there was an error the slave is going to stop, leave the
7686 file so that we can re-execute this event at START SLAVE.
7687 */
7688
3/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 79 times.
✗ Branch 3 not taken.
88 if (!error) mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
7689
7690
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 my_free(buf);
7691 88 return error;
7692 90 }
7693
7694 /*****************************************************************************
7695 Load_query_generator is used to generate the LOAD DATA statement for binlog
7696 ******************************************************************************/
7697
7698 4016 Load_query_generator::Load_query_generator(THD *thd_arg, const sql_exchange *ex,
7699 const char *db_arg,
7700 const char *table_name_arg,
7701 bool is_concurrent_arg, bool replace,
7702 4016 bool ignore)
7703 4016 : str((char *)buf, BUF_SIZE, &my_charset_bin),
7704 4016 thd(thd_arg),
7705 4016 sql_ex(ex),
7706 4016 db(db_arg),
7707
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 table_name(table_name_arg ? table_name_arg : ""),
7708 4016 fname(ex->file_name),
7709 4016 is_concurrent(is_concurrent_arg),
7710 4016 has_replace(replace),
7711 4016 has_ignore(ignore) {
7712 4016 str.length(0);
7713 4016 }
7714
7715 4016 const String *Load_query_generator::generate(size_t *fn_start, size_t *fn_end) {
7716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4016 times.
4016 assert(thd->lex->sql_command == SQLCOM_LOAD);
7717 4016 auto cmd = down_cast<Sql_cmd_load_table *>(thd->lex->m_sql_cmd);
7718
7719
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append("LOAD DATA ");
7720
7721
3/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 3996 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
4016 if (is_concurrent) str.append("CONCURRENT ");
7722
7723
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 if (fn_start) *fn_start = str.length() - 1;
7724
7725
3/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 3971 times.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
4016 if (cmd->m_is_local_file) str.append("LOCAL ");
7726
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append("INFILE ");
7727 4016 pretty_print_str(&str, fname, strlen(fname));
7728
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append(" ");
7729
7730
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4008 times.
4016 if (has_replace)
7731
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 str.append("REPLACE ");
7732
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 3922 times.
4008 else if (has_ignore)
7733
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 str.append("IGNORE ");
7734
7735
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append("INTO");
7736
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 if (fn_end) *fn_end = str.length();
7737
7738
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append(" TABLE ");
7739
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append(table_name);
7740
7741
2/2
✓ Branch 0 taken 1294 times.
✓ Branch 1 taken 2722 times.
4016 if (sql_ex->cs != nullptr) {
7742
1/2
✓ Branch 0 taken 1294 times.
✗ Branch 1 not taken.
1294 str.append(" CHARACTER SET ");
7743
1/2
✓ Branch 0 taken 1294 times.
✗ Branch 1 not taken.
1294 str.append(sql_ex->cs->csname);
7744 }
7745
7746 /* We have to create all optional fields as the default is not empty */
7747
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append(" FIELDS TERMINATED BY ");
7748 4016 pretty_print_str(&str, sql_ex->field.field_term);
7749
7750
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4004 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
4016 if (sql_ex->field.opt_enclosed) str.append(" OPTIONALLY ");
7751
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append(" ENCLOSED BY ");
7752 4016 pretty_print_str(&str, sql_ex->field.enclosed);
7753
7754
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append(" ESCAPED BY ");
7755 4016 pretty_print_str(&str, sql_ex->field.escaped);
7756
7757
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append(" LINES TERMINATED BY ");
7758 4016 pretty_print_str(&str, sql_ex->line.line_term);
7759
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4000 times.
4016 if (sql_ex->line.line_start->length() > 0) {
7760
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 str.append(" STARTING BY ");
7761 16 pretty_print_str(&str, sql_ex->line.line_start);
7762 }
7763
7764
2/2
✓ Branch 0 taken 1307 times.
✓ Branch 1 taken 2709 times.
4016 if (sql_ex->skip_lines > 0) {
7765
1/2
✓ Branch 0 taken 1307 times.
✗ Branch 1 not taken.
1307 str.append(" IGNORE ");
7766 1307 str.append_ulonglong(sql_ex->skip_lines);
7767
1/2
✓ Branch 0 taken 1307 times.
✗ Branch 1 not taken.
1307 str.append(" LINES ");
7768 }
7769
7770 /* prepare fields-list */
7771
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 if (!cmd->m_opt_fields_or_vars.empty()) {
7772
1/2
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
4016 str.append(" (");
7773
7774
6/10
✓ Branch 0 taken 4016 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4016 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4137 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8153 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4137 times.
✓ Branch 9 taken 4016 times.
8153 for (Item *item : cmd->m_opt_fields_or_vars) {
7775
7/10
✓ Branch 0 taken 4137 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 4123 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✓ Branch 8 taken 4123 times.
✓ Branch 9 taken 14 times.
4137 if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
7776
1/2
✓ Branch 0 taken 4123 times.
✗ Branch 1 not taken.
4123 append_identifier(thd, &str, item->item_name.ptr(),
7777 strlen(item->item_name.ptr()));
7778 else
7779
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 item->print(thd, &str, QT_ORDINARY);
7780
2/4
✓ Branch 0 taken 4137 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4137 times.
✗ Branch 3 not taken.
4137 str.append(", ");
7781 }
7782 // remove the last ", "
7783 4016 str.length(str.length() - 2);
7784 4016 str.append(')');
7785 }
7786
7787
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 4001 times.
4016 if (!cmd->m_opt_set_fields.empty()) {
7788
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 List_iterator<String> ls(*cmd->m_opt_set_expr_strings);
7789
7790
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 str.append(" SET ");
7791
7792
6/10
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 17 times.
✓ Branch 9 taken 15 times.
32 for (Item *item : cmd->m_opt_set_fields) {
7793 17 String *s = ls++;
7794
7795
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 append_identifier(thd, &str, item->item_name.ptr(),
7796 strlen(item->item_name.ptr()));
7797
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 str.append(*s);
7798
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 str.append(", ");
7799 }
7800 // remove the last ", "
7801 15 str.length(str.length() - 2);
7802 }
7803
7804 4016 return &str;
7805 }
7806
7807 #endif // MYSQL_SERVER
7808 #ifndef NDEBUG
7809 #ifdef MYSQL_SERVER
7810 static uchar dbug_extra_row_ndb_info_val = 0;
7811 static int dbug_extra_row_ndb_info_val_limit = 0;
7812
7813 /**
7814 set_extra_data
7815
7816 Called during self-test to generate various
7817 self-consistent binlog row event extra
7818 thread data structures which can be checked
7819 when reading the binlog.
7820
7821 @note if you are using this debug point, find the number of times this
7822 method is used for your test and then use that value for the reset_limit
7823 parameter in order to avoid inter test contamination.
7824
7825 @param arr Buffer to use
7826 @param reset_limit the limit upon which the counters reset
7827 */
7828 623 static const uchar *set_extra_data(uchar *arr, int reset_limit) {
7829 623 uchar val = (dbug_extra_row_ndb_info_val++) %
7830 623 (EXTRA_ROW_INFO_MAX_PAYLOAD + 1); /* 0 .. MAX_PAYLOAD + 1 */
7831 623 arr[EXTRA_ROW_INFO_LEN_OFFSET] = val + EXTRA_ROW_INFO_HEADER_LENGTH;
7832 623 arr[EXTRA_ROW_INFO_FORMAT_OFFSET] = val;
7833
2/2
✓ Branch 0 taken 69833 times.
✓ Branch 1 taken 623 times.
70456 for (uchar i = 0; i < val; i++) arr[EXTRA_ROW_INFO_HEADER_LENGTH + i] = val;
7834
7835 623 dbug_extra_row_ndb_info_val_limit++;
7836
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 621 times.
623 if (dbug_extra_row_ndb_info_val_limit == reset_limit) {
7837 2 dbug_extra_row_ndb_info_val = 0;
7838 2 dbug_extra_row_ndb_info_val_limit = 0;
7839 }
7840
7841 623 return arr;
7842 }
7843
7844 #endif // #ifdef MYSQL_SERVER
7845
7846 /**
7847 check_extra_row_ndb_info
7848
7849 Called during self-test to check that
7850 binlog row event extra data is self-
7851 consistent as defined by the set_extra_data
7852 function above.
7853
7854 Will assert(false) if not.
7855 */
7856 623 static void check_extra_row_ndb_info(uchar *extra_row_ndb_info) {
7857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 623 times.
623 assert(extra_row_ndb_info);
7858 623 size_t len = extra_row_ndb_info[EXTRA_ROW_INFO_LEN_OFFSET];
7859 623 size_t val = len - EXTRA_ROW_INFO_HEADER_LENGTH;
7860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 623 times.
623 assert(extra_row_ndb_info[EXTRA_ROW_INFO_FORMAT_OFFSET] == val);
7861
2/2
✓ Branch 0 taken 69833 times.
✓ Branch 1 taken 623 times.
70456 for (size_t i = 0; i < val; i++) {
7862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69833 times.
69833 assert(extra_row_ndb_info[EXTRA_ROW_INFO_HEADER_LENGTH + i] == val);
7863 }
7864 623 }
7865
7866 #endif // #ifndef NDEBUG
7867
7868 52368022 int get_rpl_part_id(partition_info *part_info) {
7869 52368022 uint32_t part_id = binary_log::Rows_event::Extra_row_info::UNDEFINED;
7870 longlong func_value;
7871
2/2
✓ Branch 0 taken 1279840 times.
✓ Branch 1 taken 51088182 times.
52368022 if (part_info != nullptr) {
7872
1/2
✓ Branch 0 taken 1279947 times.
✗ Branch 1 not taken.
1279840 part_info->get_partition_id(part_info, &part_id, &func_value);
7873 }
7874 52368129 return static_cast<int>(part_id);
7875 }
7876
7877 /**************************************************************************
7878 Rows_log_event member functions
7879 **************************************************************************/
7880
7881 #ifdef MYSQL_SERVER
7882 9282794 Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg,
7883 const Table_id &tid, MY_BITMAP const *cols,
7884 bool using_trans, Log_event_type event_type,
7885 const unsigned char *extra_row_ndb_info)
7886 : binary_log::Rows_event(event_type),
7887 Log_event(thd_arg, 0,
7888 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
7889 : Log_event::EVENT_STMT_CACHE,
7890 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
7891 9283244 m_curr_row(nullptr),
7892 9283244 m_curr_row_end(nullptr),
7893 9283244 m_key(nullptr),
7894 9283244 m_key_info(nullptr),
7895
1/2
✓ Branch 0 taken 4641519 times.
✗ Branch 1 not taken.
9283244 m_distinct_keys(Key_compare(&m_key_info)),
7896 9283220 m_distinct_key_spare_buf(nullptr),
7897
4/6
✓ Branch 0 taken 4308773 times.
✓ Branch 1 taken 332776 times.
✓ Branch 2 taken 4641636 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4641669 times.
✗ Branch 5 not taken.
18566008 m_fields{tbl_arg, Replicated_columns_view::OUTBOUND} {
7898
1/2
✓ Branch 0 taken 4641604 times.
✗ Branch 1 not taken.
9283312 DBUG_TRACE;
7899 9283208 common_header->type_code = event_type;
7900 9283208 m_row_count = 0;
7901 9283208 m_table_id = tid;
7902
1/2
✓ Branch 0 taken 4641604 times.
✗ Branch 1 not taken.
9283208 m_width = tbl_arg ? this->m_fields.filtered_size() : 1;
7903 9283240 m_rows_buf = nullptr;
7904 9283240 m_rows_cur = nullptr;
7905 9283240 m_rows_end = nullptr;
7906 9283240 m_flags = 0;
7907 9283240 m_type = event_type;
7908
7909
5/6
✓ Branch 0 taken 4641621 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4641608 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 4641587 times.
✓ Branch 5 taken 17 times.
9283240 assert(tbl_arg && tbl_arg->s && tid.is_valid());
7910
7911
2/2
✓ Branch 0 taken 1780 times.
✓ Branch 1 taken 4639807 times.
9283174 if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS)
7912 3560 set_flags(NO_FOREIGN_KEY_CHECKS_F);
7913
2/2
✓ Branch 0 taken 1528 times.
✓ Branch 1 taken 4640059 times.
9283174 if (thd_arg->variables.option_bits & OPTION_RELAXED_UNIQUE_CHECKS)
7914 3056 set_flags(RELAXED_UNIQUE_CHECKS_F);
7915 #ifndef NDEBUG
7916 uchar extra_data[255];
7917
3/4
✓ Branch 0 taken 4641515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 620 times.
✓ Branch 3 taken 4640895 times.
9283174 DBUG_EXECUTE_IF("extra_row_ndb_info_set_618",
7918 /* Set extra row data to a known value */
7919 extra_row_ndb_info = set_extra_data(extra_data, 618););
7920
3/4
✓ Branch 0 taken 4641563 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4641560 times.
9283030 DBUG_EXECUTE_IF("extra_row_ndb_info_set_3",
7921 /* Set extra row data to a known value */
7922 extra_row_ndb_info = set_extra_data(extra_data, 3););
7923 #endif
7924 9283126 partition_info *part_info = tbl_arg->part_info;
7925
1/2
✓ Branch 0 taken 4641584 times.
✗ Branch 1 not taken.
9283126 auto part_id = get_rpl_part_id(part_info);
7926
2/2
✓ Branch 0 taken 414869 times.
✓ Branch 1 taken 4226715 times.
9283168 if (part_id != binary_log::Rows_event::Extra_row_info::UNDEFINED) {
7927 829738 m_extra_row_info.set_partition_id(part_id);
7928 }
7929 /* Copy Extra ndb data from thd into new event */
7930
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 4640961 times.
9283168 if (extra_row_ndb_info) {
7931 /* Copy Extra data from thd into new event */
7932 1246 int extra_row_ndb_info_len = extra_row_ndb_info[EXTRA_ROW_INFO_LEN_OFFSET];
7933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 623 times.
1246 assert(extra_row_ndb_info_len >= EXTRA_ROW_INFO_HEADER_LENGTH);
7934
7935
1/2
✓ Branch 0 taken 522 times.
✗ Branch 1 not taken.
1246 m_extra_row_info.set_ndb_info(extra_row_ndb_info, extra_row_ndb_info_len);
7936 }
7937
7938 /* if bitmap_init fails, caught in is_valid() */
7939
2/4
✓ Branch 0 taken 4641653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4641626 times.
✗ Branch 3 not taken.
9282966 if (likely(!bitmap_init(&m_cols,
7940 9282966 m_width <= sizeof(m_bitbuf) * 8 ? m_bitbuf : nullptr,
7941
2/2
✓ Branch 0 taken 4640349 times.
✓ Branch 1 taken 1134 times.
9282966 m_width))) {
7942 /* Cols can be zero if this is a dummy binrows event */
7943
2/2
✓ Branch 0 taken 4641585 times.
✓ Branch 1 taken 55 times.
9283252 if (likely(cols != nullptr)) {
7944 // 'cols' may have additional hidden columns at the end.
7945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4641585 times.
9283170 assert(cols->n_bits >= m_cols.n_bits);
7946
1/2
✓ Branch 0 taken 4641509 times.
✗ Branch 1 not taken.
9283170 bitmap_n_copy(&m_cols, cols);
7947 }
7948 } else {
7949 // Needed because bitmap_init() does not set it to null on failure
7950 m_cols.bitmap = nullptr;
7951 }
7952
7953
2/4
✓ Branch 0 taken 4641645 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4641645 times.
9283128 if (bitmap_init(&write_set_backup, nullptr, tbl_arg->s->fields)) {
7954 write_set_backup.bitmap = nullptr; /* purecov: deadcode */
7955 }
7956
7957 /*
7958 -Check that malloc() succeeded in allocating memory for the rows
7959 buffer and the COLS vector.
7960 -Checking that an Update_rows_log_event
7961 is valid is done while setting the Update_rows_log_event::is_valid
7962 */
7963
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4641645 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9283290 common_header->set_is_valid(m_rows_buf && m_cols.bitmap &&
7964 write_set_backup.bitmap);
7965 }
7966 #endif
7967
7968 11335548 Rows_log_event::Rows_log_event(
7969 const char *buf, const Format_description_event *description_event)
7970 : binary_log::Rows_event(buf, description_event),
7971 Log_event(header(), footer()),
7972 11335652 m_row_count(0),
7973 #ifdef MYSQL_SERVER
7974 11254118 m_table(nullptr),
7975 #endif
7976 11335762 m_rows_buf(nullptr),
7977 11335762 m_rows_cur(nullptr),
7978 11335762 m_rows_end(nullptr)
7979 #if defined(MYSQL_SERVER)
7980 ,
7981 11254228 m_curr_row(nullptr),
7982 11254228 m_curr_row_end(nullptr),
7983 11254228 m_key(nullptr),
7984 11254228 m_key_info(nullptr),
7985
1/2
✓ Branch 0 taken 5627046 times.
✗ Branch 1 not taken.
11254228 m_distinct_keys(Key_compare(&m_key_info)),
7986 11254202 m_distinct_key_spare_buf(nullptr),
7987
2/4
✓ Branch 0 taken 5627118 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5627131 times.
✗ Branch 3 not taken.
22508210 m_fields(Replicated_columns_view::INBOUND)
7988 #endif
7989 {
7990
1/2
✓ Branch 0 taken 5667883 times.
✗ Branch 1 not taken.
11335792 DBUG_TRACE;
7991
3/4
✓ Branch 0 taken 5627114 times.
✓ Branch 1 taken 40767 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5627114 times.
11335766 if (!is_valid()) return;
7992
7993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5667885 times.
11335762 assert(header()->type_code == m_type);
7994
7995
2/2
✓ Branch 0 taken 658 times.
✓ Branch 1 taken 5667167 times.
11335770 if (m_extra_row_info.have_ndb_info())
7996
3/4
✓ Branch 0 taken 658 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 623 times.
✓ Branch 3 taken 35 times.
1316 DBUG_EXECUTE_IF("extra_row_ndb_info_check",
7997 /* Check extra data has expected value */
7998 check_extra_row_ndb_info(m_extra_row_info.get_ndb_info()););
7999
8000 /*
8001 m_cols and m_cols_ai are of the type MY_BITMAP, which are members of
8002 class Rows_log_event, and are used while applying the row events on
8003 the slave.
8004 The bitmap integer is initialized by copying the contents of the
8005 vector column_before_image for m_cols.bitamp, and vector
8006 column_after_image for m_cols_ai.bitmap. m_cols_ai is only initialized
8007 for UPDATE_ROWS_EVENTS, else it is equal to the before image.
8008 */
8009 /* if bitmap_init fails, is_valid will be set to false */
8010
2/4
✓ Branch 0 taken 5667895 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5667883 times.
✗ Branch 3 not taken.
11335618 if (likely(!bitmap_init(&m_cols,
8011 11335618 m_width <= sizeof(m_bitbuf) * 8 ? m_bitbuf : nullptr,
8012
2/2
✓ Branch 0 taken 5666695 times.
✓ Branch 1 taken 1114 times.
11335618 m_width))) {
8013
1/2
✓ Branch 0 taken 5667892 times.
✗ Branch 1 not taken.
11335766 if (!columns_before_image.empty()) {
8014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5667892 times.
11335784 assert(n_bits_len == (m_width + 7) / 8);
8015 11335784 memcpy(m_cols.bitmap, &columns_before_image[0], n_bits_len);
8016
1/2
✓ Branch 0 taken 5667882 times.
✗ Branch 1 not taken.
11335782 create_last_word_mask(&m_cols);
8017
1/2
✓ Branch 0 taken 5667853 times.
✗ Branch 1 not taken.
11335764 DBUG_DUMP("m_cols", (uchar *)m_cols.bitmap, no_bytes_in_map(&m_cols));
8018 } // end if columns_before_image.empty()
8019 else {
8020 if (m_cols.bitmap != m_bitbuf) bitmap_free(&m_cols);
8021 m_cols.bitmap = nullptr;
8022 }
8023 } else {
8024 // Needed because bitmap_init() does not set it to null on failure
8025 m_cols.bitmap = nullptr;
8026 common_header->set_is_valid(false);
8027 return;
8028 }
8029 11335706 m_cols_ai.bitmap =
8030 11335706 m_cols.bitmap; // See explanation below while setting is_valid.
8031
8032
2/2
✓ Branch 0 taken 5441513 times.
✓ Branch 1 taken 226340 times.
11335706 if (m_type == binary_log::UPDATE_ROWS_EVENT ||
8033
1/2
✓ Branch 0 taken 5441513 times.
✗ Branch 1 not taken.
10883026 m_type == binary_log::UPDATE_ROWS_EVENT_V1 ||
8034
2/2
✓ Branch 0 taken 7213 times.
✓ Branch 1 taken 5434300 times.
10883026 m_type == binary_log::PARTIAL_UPDATE_ROWS_EVENT) {
8035 /* if bitmap_init fails, is_valid will be set to false*/
8036
2/4
✓ Branch 0 taken 233553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 233553 times.
✗ Branch 3 not taken.
467106 if (likely(!bitmap_init(
8037 &m_cols_ai,
8038 467106 m_width <= sizeof(m_bitbuf_ai) * 8 ? m_bitbuf_ai : nullptr,
8039
2/2
✓ Branch 0 taken 233544 times.
✓ Branch 1 taken 9 times.
467106 m_width))) {
8040
1/2
✓ Branch 0 taken 233553 times.
✗ Branch 1 not taken.
467106 if (!columns_after_image.empty()) {
8041 467106 memcpy(m_cols_ai.bitmap, &columns_after_image[0], n_bits_len);
8042
1/2
✓ Branch 0 taken 233553 times.
✗ Branch 1 not taken.
467106 create_last_word_mask(&m_cols_ai);
8043
1/2
✓ Branch 0 taken 233553 times.
✗ Branch 1 not taken.
467106 DBUG_DUMP("m_cols_ai", (uchar *)m_cols_ai.bitmap,
8044 no_bytes_in_map(&m_cols_ai));
8045 } else {
8046 if (m_cols_ai.bitmap != m_bitbuf_ai) bitmap_free(&m_cols_ai);
8047 m_cols_ai.bitmap = nullptr;
8048 }
8049 } else {
8050 // Needed because bitmap_init() does not set it to null on failure
8051 m_cols_ai.bitmap = nullptr;
8052 common_header->set_is_valid(false);
8053 return;
8054 }
8055 }
8056
8057 /*
8058 m_rows_buf, m_curr_row and m_rows_end are pointers to the vector rows.
8059 m_rows_buf is the pointer to the first byte of first row in the event.
8060 m_curr_row points to current row being applied on the slave. Initially,
8061 this points to the same element as m_rows_buf in the vector.
8062 m_rows_end points to the last byte in the last row in the event.
8063
8064 These pointers are used while applying the events on to the slave, and
8065 are not required for decoding.
8066 */
8067
1/2
✓ Branch 0 taken 5667889 times.
✗ Branch 1 not taken.
11335706 if (likely(!row.empty())) {
8068 11335778 m_rows_buf = &row[0];
8069 #if defined(MYSQL_SERVER)
8070 11254226 m_curr_row = m_rows_buf;
8071 #endif
8072 11335760 m_rows_end = m_rows_buf + row.size() - 1;
8073 11335738 m_rows_cur = m_rows_end;
8074 }
8075
8076
2/4
✓ Branch 0 taken 5667898 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5667898 times.
11335736 if (bitmap_init(&write_set_backup, nullptr, m_cols.n_bits)) {
8077 write_set_backup.bitmap = nullptr; /* purecov: deadcode */
8078 }
8079
8080 /*
8081 -Check that malloc() succeeded in allocating memory for the row
8082 buffer and the COLS vector.
8083 */
8084
3/4
✓ Branch 0 taken 5667896 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 5667898 times.
✗ Branch 3 not taken.
22671592 common_header->set_is_valid(m_rows_buf && m_cols.bitmap &&
8085
2/2
✓ Branch 0 taken 5667896 times.
✓ Branch 1 taken 2 times.
11335796 write_set_backup.bitmap);
8086 }
8087
8088 20618554 Rows_log_event::~Rows_log_event() {
8089
1/2
✓ Branch 0 taken 10309394 times.
✗ Branch 1 not taken.
20618554 if (m_cols.bitmap) {
8090
2/2
✓ Branch 0 taken 10307242 times.
✓ Branch 1 taken 2152 times.
20618788 if (m_cols.bitmap == m_bitbuf) // no my_malloc happened
8091 20614484 m_cols.bitmap = nullptr; // so no my_free in bitmap_free
8092 20618788 bitmap_free(&m_cols); // To pair with bitmap_init().
8093 }
8094
2/2
✓ Branch 0 taken 349598 times.
✓ Branch 1 taken 9959795 times.
20618786 if (this->m_local_cols_ai.bitmap != nullptr &&
8095
2/2
✓ Branch 0 taken 26001 times.
✓ Branch 1 taken 323597 times.
699196 this->m_local_cols_ai.bitmap != this->m_local_cols.bitmap) {
8096 52002 bitmap_free(&this->m_local_cols_ai);
8097 }
8098
2/2
✓ Branch 0 taken 349600 times.
✓ Branch 1 taken 9959793 times.
20618786 if (this->m_local_cols.bitmap != nullptr) {
8099 699200 bitmap_free(&this->m_local_cols);
8100 }
8101
8102
1/2
✓ Branch 0 taken 10309531 times.
✗ Branch 1 not taken.
20618802 if (write_set_backup.bitmap) {
8103 20619062 bitmap_free(&write_set_backup);
8104 }
8105 }
8106
8107 #ifdef MYSQL_SERVER
8108 4096600 int Rows_log_event::unpack_current_row(const Relay_log_info *const rli,
8109 MY_BITMAP const *cols,
8110 bool is_after_image, bool only_seek) {
8111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4096600 times.
4096600 assert(m_table);
8112
8113 enum_row_image_type row_image_type;
8114
2/2
✓ Branch 0 taken 3424530 times.
✓ Branch 1 taken 672070 times.
4096600 if (is_after_image) {
8115
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3424634 times.
3424530 assert(get_general_type_code() != binary_log::DELETE_ROWS_EVENT);
8116 6849274 row_image_type = (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT)
8117
2/2
✓ Branch 0 taken 624770 times.
✓ Branch 1 taken 2799870 times.
3424640 ? enum_row_image_type::UPDATE_AI
8118 : enum_row_image_type::WRITE_AI;
8119 } else {
8120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 672136 times.
672070 assert(get_general_type_code() != binary_log::WRITE_ROWS_EVENT);
8121 1344272 row_image_type = (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT)
8122
2/2
✓ Branch 0 taken 624779 times.
✓ Branch 1 taken 47357 times.
672136 ? enum_row_image_type::UPDATE_BI
8123 : enum_row_image_type::DELETE_BI;
8124 }
8125 bool has_value_options =
8126 4096776 (get_type_code() == binary_log::PARTIAL_UPDATE_ROWS_EVENT);
8127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4096709 times.
4096709 ASSERT_OR_RETURN_ERROR(m_curr_row <= m_rows_end, HA_ERR_CORRUPT_EVENT);
8128
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 4096738 times.
4096864 if (::unpack_row(rli, m_table, m_width, m_curr_row, cols, &m_curr_row_end,
8129 4096709 m_rows_end, row_image_type, has_value_options, only_seek)) {
8130 126 int error = thd->get_stmt_da()->mysql_errno();
8131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
126 assert(error);
8132 126 return error;
8133 }
8134
8135 // After the row is unpacked, we need to update all generated columns
8136 // that aren't included in the row image provided by the source, that is,
8137 // hidden generated columns for functional indexes, generated columns
8138 // that have associated indexes, stored generated columns for which base
8139 // columns have changed and stored generated columns that only exist on
8140 // the replica. We do it in two steps, first all the generated columns
8141 // that aren't functional indexes and then the columns for functional
8142 // indexes, since functional indexes may use generated columns as the
8143 // base column for the index.
8144
2/2
✓ Branch 0 taken 25450 times.
✓ Branch 1 taken 4071146 times.
4096738 if (m_table->has_gcol()) {
8145
2/2
✓ Branch 0 taken 25419 times.
✓ Branch 1 taken 31 times.
25450 if (!only_seek) {
8146 Table_columns_view<> updatable_columns_view{
8147 // A table view for generated columns that need to be updated on the
8148 // replica, excluding columns for functional indexes
8149 25419 this->m_table,
8150 50685 [=](TABLE const *table, size_t column_index) -> bool {
8151 50685 auto field = table->field[column_index];
8152
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 50364 times.
50685 if (field->is_field_for_functional_index()) // Always exclude
8153 // functional indexes
8154 321 return true;
8155
6/6
✓ Branch 0 taken 16900 times.
✓ Branch 1 taken 33464 times.
✓ Branch 2 taken 8501 times.
✓ Branch 3 taken 8399 times.
✓ Branch 4 taken 8501 times.
✓ Branch 5 taken 41863 times.
67264 if (!is_after_image && // Always exclude virtual generated columns
8156 16900 field->is_virtual_gcol()) // if not processing after-image
8157 8501 return true;
8158
2/2
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 41375 times.
41863 if (field->m_indexed) // Never exclude generated columns that
8159 // have indexes
8160 488 return false;
8161
2/2
✓ Branch 0 taken 41346 times.
✓ Branch 1 taken 29 times.
41375 if (bitmap_is_overlapping( // Never exclude generated columns for
8162 // which the base column value changed.
8163 41375 table->write_set, &field->gcol_info->base_columns_map))
8164 41346 return false;
8165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!is_after_image) // Else, exclude if not in after-image
8166 return true;
8167 return column_index <
8168 29 this->m_cols // Else, exclude generated columns that
8169
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
29 .n_bits || // also exists on the source
8170 29 field->is_virtual_gcol(); // or that are virtual
8171 },
8172
1/2
✓ Branch 0 taken 25419 times.
✗ Branch 1 not taken.
25419 Table_columns_view<>::VFIELDS_ONLY};
8173
8174
3/4
✓ Branch 0 taken 25054 times.
✓ Branch 1 taken 365 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25419 times.
50473 if (updatable_columns_view.filtered_size() != 0 &&
8175
2/4
✓ Branch 0 taken 25054 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 25054 times.
25054 this->update_generated_columns(
8176 25054 updatable_columns_view.get_included_fields_bitmap())) {
8177 return thd->get_stmt_da()->mysql_errno(); /* purecov: deadcode */
8178 }
8179
1/2
✓ Branch 0 taken 25419 times.
✗ Branch 1 not taken.
25419 }
8180
4/4
✓ Branch 0 taken 16942 times.
✓ Branch 1 taken 8508 times.
✓ Branch 2 taken 162 times.
✓ Branch 3 taken 25288 times.
42392 if (is_after_image &&
8181
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 16780 times.
16942 !bitmap_is_clear_all(&this->m_table->fields_for_functional_indexes)) {
8182
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 40 times.
162 if (this->update_generated_columns(
8183 162 this->m_table->fields_for_functional_indexes))
8184 122 return thd->get_stmt_da()->mysql_errno(); /* purecov: deadcode */
8185 }
8186 }
8187
8188 4096474 return 0;
8189 }
8190
8191 25216 int Rows_log_event::update_generated_columns(
8192 MY_BITMAP const &fields_to_update) {
8193
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25216 times.
25216 assert(!bitmap_is_clear_all(&fields_to_update)); // Do not call this function
8194 // if there is nothing to do
8195 // Readjust the size of the backup bitmap, if needed
8196
2/2
✓ Branch 0 taken 121 times.
✓ Branch 1 taken 25095 times.
25216 if (this->write_set_backup.n_bits != this->m_table->s->fields) {
8197 121 bitmap_free(&this->write_set_backup);
8198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
121 if (bitmap_init(&this->write_set_backup, nullptr,
8199 121 this->m_table->s->fields)) {
8200 return HA_ERR_OUT_OF_MEM; /* purecov: deadcode */
8201 }
8202 }
8203 // Make a copy of the write set, and mark all hidden generated columns.
8204 25216 bitmap_copy(&this->write_set_backup, this->m_table->write_set);
8205 25216 bitmap_union(this->m_table->write_set, &fields_to_update);
8206 // Calculate the values for all columns set in param `fields_to_update.
8207 25216 auto res = update_generated_write_fields(&fields_to_update, this->m_table);
8208 // Restore the write set before return
8209 25216 bitmap_copy(this->m_table->write_set, &this->write_set_backup);
8210 25216 return res;
8211 }
8212 #endif // ifdef MYSQL_SERVER
8213
8214 49033302 size_t Rows_log_event::get_data_size() {
8215
1/2
✓ Branch 0 taken 49033788 times.
✗ Branch 1 not taken.
49033302 int const general_type_code = get_general_type_code();
8216
8217 uchar buf[sizeof(m_width) + 1];
8218
1/2
✓ Branch 0 taken 49033567 times.
✗ Branch 1 not taken.
49033788 uchar *end = net_store_length(buf, m_width);
8219
8220
2/6
✓ Branch 0 taken 49034146 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49034146 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
49033567 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_source",
8221 return 6 + no_bytes_in_map(&m_cols) + (end - buf) +
8222 (general_type_code == binary_log::UPDATE_ROWS_EVENT
8223 ? no_bytes_in_map(&m_cols_ai)
8224 : 0) +
8225 (m_rows_cur - m_rows_buf););
8226
8227 49034146 int data_size = 0;
8228 49034146 bool is_v2_event =
8229 49034146 common_header->type_code > binary_log::DELETE_ROWS_EVENT_V1;
8230
2/2
✓ Branch 0 taken 49034118 times.
✓ Branch 1 taken 28 times.
49034146 if (is_v2_event) {
8231 49034118 data_size = Binary_log_event::ROWS_HEADER_LEN_V2;
8232
2/2
✓ Branch 0 taken 1235 times.
✓ Branch 1 taken 49032559 times.
49034118 if (m_extra_row_info.have_ndb_info())
8233 1235 data_size +=
8234
1/2
✓ Branch 0 taken 1235 times.
✗ Branch 1 not taken.
1235 EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_ndb_length();
8235
8236
2/2
✓ Branch 0 taken 1117369 times.
✓ Branch 1 taken 47916185 times.
49033794 if (m_extra_row_info.have_part())
8237 1117736 data_size +=
8238
1/2
✓ Branch 0 taken 1117736 times.
✗ Branch 1 not taken.
1117369 EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_part_length();
8239 } else {
8240 28 data_size = Binary_log_event::ROWS_HEADER_LEN_V1;
8241 }
8242 49033949 data_size += no_bytes_in_map(&m_cols);
8243 49033949 data_size += (uint)(end - buf);
8244
8245
2/2
✓ Branch 0 taken 3880419 times.
✓ Branch 1 taken 45153530 times.
49033949 if (general_type_code == binary_log::UPDATE_ROWS_EVENT)
8246 3880419 data_size += no_bytes_in_map(&m_cols_ai);
8247
8248 49033949 data_size += (uint)(m_rows_cur - m_rows_buf);
8249 49033949 return data_size;
8250 }
8251
8252 #ifdef MYSQL_SERVER
8253 51542019 int Rows_log_event::do_add_row_data(uchar *row_data, size_t length) {
8254 /*
8255 When the table has a primary key, we would probably want, by default, to
8256 log only the primary key value instead of the entire "before image". This
8257 would save binlog space. TODO
8258 */
8259
1/2
✓ Branch 0 taken 51542663 times.
✗ Branch 1 not taken.
51542019 DBUG_TRACE;
8260
4/8
✓ Branch 0 taken 51542618 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 51542650 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 46 times.
✓ Branch 5 taken 51542604 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
51542663 DBUG_PRINT("enter", ("row_data: %p length: %lu", row_data, (ulong)length));
8261
8262 /*
8263 If length is zero, there is nothing to write, so we just
8264 return. Note that this is not an optimization, since calling
8265 realloc() with size 0 means free().
8266 */
8267
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 51542516 times.
51542526 if (length == 0) {
8268 10 m_row_count++;
8269 10 return 0;
8270 }
8271
8272
1/2
✓ Branch 0 taken 51542582 times.
✗ Branch 1 not taken.
51542516 DBUG_DUMP("row_data", row_data, min<size_t>(length, 32));
8273
8274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51542582 times.
51542582 assert(m_rows_buf <= m_rows_cur);
8275
6/6
✓ Branch 0 taken 46901055 times.
✓ Branch 1 taken 4641527 times.
✓ Branch 2 taken 46901052 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 46900978 times.
✓ Branch 5 taken 74 times.
51542582 assert(!m_rows_buf || (m_rows_end && m_rows_buf < m_rows_end));
8276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51542505 times.
51542505 assert(m_rows_cur <= m_rows_end);
8277
8278 /* The cast will always work since m_rows_cur <= m_rows_end */
8279
2/2
✓ Branch 0 taken 5947888 times.
✓ Branch 1 taken 45594617 times.
51542505 if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length) {
8280 5947888 size_t const block_size = 1024;
8281 5947888 ulong cur_size = m_rows_cur - m_rows_buf;
8282
2/4
✓ Branch 0 taken 5947917 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5947917 times.
5947888 DBUG_EXECUTE_IF("simulate_too_big_row_case1",
8283 cur_size = UINT_MAX32 - (block_size * 10);
8284 length = UINT_MAX32 - (block_size * 10););
8285
2/4
✓ Branch 0 taken 5947937 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5947937 times.
5947917 DBUG_EXECUTE_IF("simulate_too_big_row_case2",
8286 cur_size = UINT_MAX32 - (block_size * 10);
8287 length = block_size * 10;);
8288
2/4
✓ Branch 0 taken 5947899 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5947899 times.
5947937 DBUG_EXECUTE_IF("simulate_too_big_row_case3", cur_size = block_size * 10;
8289 length = UINT_MAX32 - (block_size * 10););
8290
2/4
✓ Branch 0 taken 5947944 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5947944 times.
5947899 DBUG_EXECUTE_IF("simulate_too_big_row_case4",
8291 cur_size = UINT_MAX32 - (block_size * 10);
8292 length = (block_size * 10) - block_size + 1;);
8293 5947944 ulong remaining_space = UINT_MAX32 - cur_size;
8294 /* Check that the new data fits within remaining space and we can add
8295 block_size without wrapping.
8296 */
8297
3/4
✓ Branch 0 taken 5947953 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 155 times.
✓ Branch 3 taken 5947798 times.
5947944 if (length > remaining_space || ((length + block_size) > remaining_space)) {
8298
0/16
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
146 LogErr(ERROR_LEVEL, ER_ROW_DATA_TOO_BIG_TO_WRITE_IN_BINLOG);
8299 return ER_BINLOG_ROW_LOGGING_FAILED;
8300 }
8301 5947798 const size_t new_alloc =
8302 5947798 block_size * ((cur_size + length + block_size - 1) / block_size);
8303
3/4
✓ Branch 0 taken 5947789 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 5947972 times.
✗ Branch 3 not taken.
5947798 if (new_alloc) row.resize(new_alloc);
8304
8305 /* If the memory moved, we need to move the pointers */
8306
6/6
✓ Branch 0 taken 5947964 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 5180127 times.
✓ Branch 3 taken 767839 times.
✓ Branch 4 taken 5180134 times.
✓ Branch 5 taken 767849 times.
5947981 if (new_alloc && &row[0] != m_rows_buf) {
8307 5180134 m_rows_buf = &row[0];
8308
2/4
✓ Branch 0 taken 5180144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5180150 times.
✗ Branch 3 not taken.
5180141 common_header->set_is_valid(m_rows_buf && m_cols.bitmap);
8309 5180122 m_rows_cur = m_rows_buf + cur_size;
8310 }
8311
8312 /*
8313 The end pointer should always be changed to point to the end of
8314 the allocated memory.
8315 */
8316 5947971 m_rows_end = m_rows_buf + new_alloc;
8317 }
8318
8319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51542588 times.
51542588 assert(m_rows_cur + length <= m_rows_end);
8320 51542588 memcpy(m_rows_cur, row_data, length);
8321 51542588 m_rows_cur += length;
8322 51542588 m_row_count++;
8323 51542588 return 0;
8324 51542598 }
8325
8326 /**
8327 Checks if any of the columns in the given table is
8328 signaled in the bitmap.
8329
8330 For each column in the given table checks if it is
8331 signaled in the bitmap. This is most useful when deciding
8332 whether a before image (BI) can be used or not for
8333 searching a row. If no column is signaled, then the
8334 image cannot be used for searching a record (regardless
8335 of using position(), index scan or table scan). Here is
8336 an example:
8337
8338 MASTER> SET @@binlog_row_image='MINIMAL';
8339 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
8340 SLAVE> CREATE TABLE t1 (a int, b int);
8341 MASTER> INSERT INTO t1 VALUES (1,2,3);
8342 MASTER> UPDATE t1 SET a=2 WHERE b=2;
8343
8344 For the update statement only the PK (column c) is
8345 logged in the before image (BI). As such, given that
8346 the slave has no column c, it will not be able to
8347 find the row, because BI has no values for the columns
8348 the slave knows about (column a and b).
8349
8350 @param table the table reference on the slave.
8351 @param cols the bitmap signaling columns available in
8352 the BI.
8353
8354 @return true if BI contains usable columns for searching,
8355 false otherwise.
8356 */
8357 64649 static bool is_any_column_signaled_for_table(TABLE *table, MY_BITMAP *cols) {
8358
1/2
✓ Branch 0 taken 64649 times.
✗ Branch 1 not taken.
64649 DBUG_TRACE;
8359
8360 71899 for (Field **ptr = table->field;
8361
5/6
✓ Branch 0 taken 71852 times.
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 71852 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 71852 times.
✓ Branch 5 taken 47 times.
71899 *ptr && ((*ptr)->field_index() < cols->n_bits); ptr++) {
8362
2/2
✓ Branch 0 taken 64602 times.
✓ Branch 1 taken 7250 times.
71852 if (bitmap_is_set(cols, (*ptr)->field_index())) return true;
8363 }
8364
8365 47 return false;
8366 64649 }
8367
8368 /**
8369 Checks if the fields in the given key are signaled in
8370 the bitmap.
8371
8372 Validates whether the before image is usable for the
8373 given key. It can be the case that the before image
8374 does not contain values for the key (eg, master was
8375 using 'minimal' option for image logging and slave has
8376 different index structure on the table). Here is an
8377 example:
8378
8379 MASTER> SET @@binlog_row_image='MINIMAL';
8380 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
8381 SLAVE> CREATE TABLE t1 (a int, b int, c int, key(a,c));
8382 MASTER> INSERT INTO t1 VALUES (1,2,3);
8383 MASTER> UPDATE t1 SET a=2 WHERE b=2;
8384
8385 When finding the row on the slave, one cannot use the
8386 index (a,c) to search for the row, because there is only
8387 data in the before image for column c. This function
8388 checks the fields needed for a given key and searches
8389 the bitmap to see if all the fields required are
8390 signaled.
8391
8392 @param keyinfo reference to key.
8393 @param cols the bitmap signaling which columns
8394 have available data.
8395
8396 @return true if all fields are signaled in the bitmap
8397 for the given key, false otherwise.
8398 */
8399 32893 static bool are_all_columns_signaled_for_key(KEY *keyinfo, MY_BITMAP *cols) {
8400
1/2
✓ Branch 0 taken 32893 times.
✗ Branch 1 not taken.
32893 DBUG_TRACE;
8401
8402
2/2
✓ Branch 0 taken 37098 times.
✓ Branch 1 taken 31442 times.
68540 for (uint i = 0; i < keyinfo->actual_key_parts; i++) {
8403 37098 uint fieldnr = keyinfo->key_part[i].fieldnr - 1;
8404
6/6
✓ Branch 0 taken 36830 times.
✓ Branch 1 taken 268 times.
✓ Branch 2 taken 1183 times.
✓ Branch 3 taken 35647 times.
✓ Branch 4 taken 1451 times.
✓ Branch 5 taken 35647 times.
37098 if (fieldnr >= cols->n_bits || !bitmap_is_set(cols, fieldnr)) return false;
8405 }
8406
8407 31442 return true;
8408 32893 }
8409
8410 /**
8411 Searches the table for a given key that can be used
8412 according to the existing values, ie, columns set
8413 in the bitmap.
8414
8415 The caller can specify which type of key to find by
8416 setting the following flags in the key_type parameter:
8417
8418 - PRI_KEY_FLAG
8419 Returns the primary key.
8420
8421 - UNIQUE_KEY_FLAG
8422 Returns a unique key (flagged with HA_NOSAME)
8423
8424 - MULTIPLE_KEY_FLAG
8425 Returns a key that is not unique (flagged with HA_NOSAME
8426 and without HA_NULL_PART_KEY) nor PK.
8427
8428 The above flags can be used together, in which case, the
8429 search is conducted in the above listed order. Eg, the
8430 following flag:
8431
8432 (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG)
8433
8434 means that a primary key is returned if it is suitable. If
8435 not then the unique keys are searched. If no unique key is
8436 suitable, then the keys are searched. Finally, if no key
8437 is suitable, MAX_KEY is returned.
8438
8439 @param table reference to the table.
8440 @param bi_cols a bitmap that filters out columns that should
8441 not be considered while searching the key.
8442 Columns that should be considered are set.
8443 @param key_type the type of key to search for.
8444
8445 @return MAX_KEY if no key, according to the key_type specified
8446 is suitable. Returns the key otherwise.
8447
8448 */
8449 49645 static uint search_key_in_table(TABLE *table, MY_BITMAP *bi_cols,
8450 uint key_type) {
8451
1/2
✓ Branch 0 taken 49645 times.
✗ Branch 1 not taken.
49645 DBUG_TRACE;
8452
8453 KEY *keyinfo;
8454 49645 uint res = MAX_KEY;
8455 uint key;
8456
8457
3/4
✓ Branch 0 taken 49645 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26431 times.
✓ Branch 3 taken 23214 times.
49645 if (key_type & PRI_KEY_FLAG && (table->s->primary_key < MAX_KEY)) {
8458
3/8
✓ Branch 0 taken 26431 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26431 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 26431 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
26431 DBUG_PRINT("debug", ("Searching for PK"));
8459 26431 keyinfo = table->s->key_info + table->s->primary_key;
8460
3/4
✓ Branch 0 taken 26431 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25334 times.
✓ Branch 3 taken 1097 times.
26431 if (are_all_columns_signaled_for_key(keyinfo, bi_cols))
8461 25334 return table->s->primary_key;
8462 }
8463
8464
1/2
✓ Branch 0 taken 24311 times.
✗ Branch 1 not taken.
24311 if (key_type & UNIQUE_KEY_FLAG) {
8465
3/8
✓ Branch 0 taken 24311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24311 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24311 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
24311 DBUG_PRINT("debug", ("Searching for UK"));
8466 24311 for (key = 0, keyinfo = table->key_info;
8467
3/4
✓ Branch 0 taken 12969 times.
✓ Branch 1 taken 23410 times.
✓ Branch 2 taken 12969 times.
✗ Branch 3 not taken.
36379 (key < table->s->keys) && (res == MAX_KEY); key++, keyinfo++) {
8468 /*
8469 - Unique keys cannot be disabled, thence we skip the check.
8470 - Skip unique keys with nullable parts
8471 - Skip primary keys
8472 - Skip functional indexes if the slave_rows_search_algorithms=INDEX_SCAN
8473 - Skip multi-valued keys as they have only part of value and can't
8474 fully identify a record
8475 */
8476 40006 if (!((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
8477
2/2
✓ Branch 0 taken 1127 times.
✓ Branch 1 taken 1097 times.
2224 (key == table->s->primary_key) ||
8478
1/2
✓ Branch 0 taken 1127 times.
✗ Branch 1 not taken.
1127 ((slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN) &&
8479
2/4
✓ Branch 0 taken 1127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1127 times.
✗ Branch 3 not taken.
1127 keyinfo->is_functional_index()) ||
8480
7/8
✓ Branch 0 taken 2224 times.
✓ Branch 1 taken 10745 times.
✓ Branch 2 taken 1127 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1125 times.
✓ Branch 6 taken 11844 times.
✓ Branch 7 taken 1125 times.
15193 keyinfo->flags & HA_MULTI_VALUED_KEY || !keyinfo->is_visible) {
8481 11844 continue;
8482 }
8483
3/4
✓ Branch 0 taken 1125 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 901 times.
✓ Branch 3 taken 224 times.
1125 res = are_all_columns_signaled_for_key(keyinfo, bi_cols) ? key : MAX_KEY;
8484
8485
2/2
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 224 times.
1125 if (res < MAX_KEY) return res;
8486 }
8487
3/8
✓ Branch 0 taken 23410 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23410 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 23410 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
23410 DBUG_PRINT("debug", ("UK has NULLABLE parts or not all columns signaled."));
8488 }
8489
8490
4/4
✓ Branch 0 taken 11867 times.
✓ Branch 1 taken 11543 times.
✓ Branch 2 taken 5967 times.
✓ Branch 3 taken 5900 times.
23410 if (key_type & MULTIPLE_KEY_FLAG && table->s->keys) {
8491
3/8
✓ Branch 0 taken 5967 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5967 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5967 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
5967 DBUG_PRINT("debug", ("Searching for K."));
8492 5967 for (key = 0, keyinfo = table->key_info;
8493
3/4
✓ Branch 0 taken 6060 times.
✓ Branch 1 taken 760 times.
✓ Branch 2 taken 6060 times.
✗ Branch 3 not taken.
6820 (key < table->s->keys) && (res == MAX_KEY); key++, keyinfo++) {
8494 /*
8495 The following indexes are skipped:
8496 - Inactive/invisible indexes.
8497 - UNIQUE NOT NULL indexes.
8498 - Indexes that do not support ha_index_next() e.g. full-text.
8499 - Primary key indexes.
8500 - Functional indexes if the slave_rows_search_algorithms=INDEX_SCAN
8501 - Skip multi-valued keys as they have only part of value and can't
8502 fully identify a record
8503 */
8504
2/4
✓ Branch 0 taken 6060 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6060 times.
✗ Branch 3 not taken.
6060 if (!(table->s->usable_indexes(current_thd).is_set(key)) ||
8505
2/2
✓ Branch 0 taken 5381 times.
✓ Branch 1 taken 676 times.
6057 ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
8506
3/4
✓ Branch 0 taken 5381 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5378 times.
✓ Branch 3 taken 3 times.
5381 !(table->file->index_flags(key, 0, true) & HA_READ_NEXT) ||
8507
1/2
✓ Branch 0 taken 5378 times.
✗ Branch 1 not taken.
5378 (key == table->s->primary_key) ||
8508
2/2
✓ Branch 0 taken 5341 times.
✓ Branch 1 taken 37 times.
5378 ((slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN) &&
8509
7/8
✓ Branch 0 taken 6057 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5341 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5300 times.
✓ Branch 5 taken 41 times.
✓ Branch 6 taken 723 times.
✓ Branch 7 taken 5337 times.
17417 keyinfo->is_functional_index()) ||
8510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5337 times.
5337 keyinfo->flags & HA_MULTI_VALUED_KEY) {
8511 723 continue;
8512 }
8513
8514
3/4
✓ Branch 0 taken 5337 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5207 times.
✓ Branch 3 taken 130 times.
5337 res = are_all_columns_signaled_for_key(keyinfo, bi_cols) ? key : MAX_KEY;
8515
8516
2/2
✓ Branch 0 taken 5207 times.
✓ Branch 1 taken 130 times.
5337 if (res < MAX_KEY) return res;
8517 }
8518
3/8
✓ Branch 0 taken 760 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 760 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 760 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
760 DBUG_PRINT("debug", ("Not all columns signaled for K."));
8519 }
8520
8521 18203 return res;
8522 49645 }
8523
8524 349247 void Rows_log_event::decide_row_lookup_algorithm_and_key() {
8525
1/2
✓ Branch 0 taken 349521 times.
✗ Branch 1 not taken.
349247 DBUG_TRACE;
8526
8527 /*
8528 Decision table:
8529 - I --> Index scan / search
8530 - T --> Table scan
8531 - Hi --> Hash over index
8532 - Ht --> Hash over the entire table
8533
8534 |--------------+-----------+------+------+------|
8535 | Index\Option | I , T , H | I, T | I, H | T, H |
8536 |--------------+-----------+------+------+------|
8537 | PK / UK | I | I | I | Hi |
8538 | K | Hi | I | Hi | Hi |
8539 | No Index | Ht | T | Ht | Ht |
8540 |--------------+-----------+------+------+------|
8541
8542 */
8543 349521 TABLE *table = this->m_table;
8544
1/2
✓ Branch 0 taken 349514 times.
✗ Branch 1 not taken.
349521 uint event_type = this->get_general_type_code();
8545 349514 MY_BITMAP *cols = &this->m_cols;
8546 349514 bool delete_update_lookup_condition = false;
8547 349514 this->m_rows_lookup_algorithm = ROW_LOOKUP_NOT_NEEDED;
8548 349514 this->m_key_index = MAX_KEY;
8549 349514 this->m_key_info = nullptr;
8550
8551 // row lookup not needed
8552
4/4
✓ Branch 0 taken 38710 times.
✓ Branch 1 taken 310804 times.
✓ Branch 2 taken 310647 times.
✓ Branch 3 taken 38867 times.
388224 if (event_type == binary_log::WRITE_ROWS_EVENT ||
8553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38710 times.
38710 (delete_update_lookup_condition =
8554
1/2
✓ Branch 0 taken 25983 times.
✗ Branch 1 not taken.
25983 ((event_type == binary_log::DELETE_ROWS_EVENT ||
8555
2/2
✓ Branch 0 taken 35119 times.
✓ Branch 1 taken 3591 times.
38710 event_type == binary_log::UPDATE_ROWS_EVENT) &&
8556
4/6
✓ Branch 0 taken 25983 times.
✓ Branch 1 taken 12727 times.
✓ Branch 2 taken 35119 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 35119 times.
103403 get_flags(COMPLETE_ROWS_F) && !m_table->file->rpl_lookup_rows()))) {
8557 /**
8558 Only TokuDB and RocksDB engines can satisfy delete/update row lookup
8559 optimization, so we don't need to check engine type here.
8560 */
8561
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 310647 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
310647 if (delete_update_lookup_condition && table->s->primary_key == MAX_KEY) {
8562 if (!table->s->rfr_lookup_warning) {
8563 sql_print_warning(
8564 "Slave: read free replication is disabled "
8565 "for TokuDB/RocksDB table `%s.%s` "
8566 "as it does not have implicit primary key, "
8567 "continue with rows lookup",
8568 print_slave_db_safe(table->s->db.str), m_table->s->table_name.str);
8569 table->s->rfr_lookup_warning = true;
8570 }
8571 } else
8572 310647 return;
8573 }
8574
8575
2/2
✓ Branch 0 taken 1493 times.
✓ Branch 1 taken 37374 times.
38867 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN))
8576 1493 goto TABLE_OR_INDEX_HASH_SCAN;
8577
8578 /* PK or UK => use LOOKUP_INDEX_SCAN */
8579 37217 this->m_key_index =
8580
1/2
✓ Branch 0 taken 37217 times.
✗ Branch 1 not taken.
37374 search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG));
8581
2/2
✓ Branch 0 taken 25674 times.
✓ Branch 1 taken 11543 times.
37217 if (this->m_key_index != MAX_KEY) {
8582
3/8
✓ Branch 0 taken 25674 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25674 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 25674 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
25674 DBUG_PRINT("info",
8583 ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
8584 25674 this->m_rows_lookup_algorithm = ROW_LOOKUP_INDEX_SCAN;
8585 25674 goto end;
8586 }
8587
8588 11543 TABLE_OR_INDEX_HASH_SCAN:
8589
8590 /*
8591 NOTE: Engines like Blackhole cannot use HASH_SCAN, because
8592 they do not synchronize reads.
8593 */
8594
4/4
✓ Branch 0 taken 12362 times.
✓ Branch 1 taken 674 times.
✓ Branch 2 taken 688 times.
✓ Branch 3 taken 12348 times.
25398 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_HASH_SCAN) ||
8595
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 12348 times.
12362 (table->file->ha_table_flags() & HA_READ_OUT_OF_SYNC))
8596 688 goto TABLE_OR_INDEX_FULL_SCAN;
8597
8598 /* search for a key to see if we can narrow the lookup domain further. */
8599
1/2
✓ Branch 0 taken 12348 times.
✗ Branch 1 not taken.
12348 this->m_key_index = search_key_in_table(
8600 table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
8601 12348 this->m_rows_lookup_algorithm = ROW_LOOKUP_HASH_SCAN;
8602
2/2
✓ Branch 0 taken 5758 times.
✓ Branch 1 taken 6590 times.
12348 if (m_key_index < MAX_KEY)
8603 5758 m_distinct_key_spare_buf =
8604
1/2
✓ Branch 0 taken 5758 times.
✗ Branch 1 not taken.
5758 (uchar *)thd->alloc(table->key_info[m_key_index].key_length);
8605
3/8
✓ Branch 0 taken 12348 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12348 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12348 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12348 DBUG_PRINT("info",
8606 ("decide_row_lookup_algorithm_and_key: decided - HASH_SCAN"));
8607 12348 goto end;
8608
8609 688 TABLE_OR_INDEX_FULL_SCAN:
8610
8611 688 this->m_key_index = MAX_KEY;
8612
8613 /* If we can use an index, try to narrow the scan a bit further. */
8614
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 608 times.
688 if (slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN)
8615
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 this->m_key_index = search_key_in_table(
8616 table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
8617
8618
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 678 times.
688 if (this->m_key_index != MAX_KEY) {
8619
3/8
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10 DBUG_PRINT("info",
8620 ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
8621 10 this->m_rows_lookup_algorithm = ROW_LOOKUP_INDEX_SCAN;
8622 } else {
8623
3/8
✓ Branch 0 taken 678 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 678 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 678 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
678 DBUG_PRINT("info",
8624 ("decide_row_lookup_algorithm_and_key: decided - TABLE_SCAN"));
8625 678 this->m_rows_lookup_algorithm = ROW_LOOKUP_TABLE_SCAN;
8626 }
8627
8628 38710 end:
8629 /* m_key_index is ready, set m_key_info now. */
8630 38710 m_key_info = m_table->key_info + m_key_index;
8631 /*
8632 m_key_info will influence key comparison code in HASH_SCAN mode,
8633 so the m_distinct_keys set should still be empty.
8634 */
8635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38710 times.
38710 assert(m_distinct_keys.empty());
8636
8637 #ifndef NDEBUG
8638 38710 const char *s =
8639 38710 ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_TABLE_SCAN)
8640
2/2
✓ Branch 0 taken 38032 times.
✓ Branch 1 taken 678 times.
76742 ? "TABLE_SCAN"
8641 38032 : ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_HASH_SCAN)
8642
2/2
✓ Branch 0 taken 12348 times.
✓ Branch 1 taken 25684 times.
38032 ? "HASH_SCAN"
8643 : "INDEX_SCAN"));
8644
8645 // only for testing purposes
8646 38710 replica_rows_last_search_algorithm_used = m_rows_lookup_algorithm;
8647
3/8
✓ Branch 0 taken 38710 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38710 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 38710 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
38710 DBUG_PRINT("debug", ("Row lookup method: %s", s));
8648 #endif
8649
2/2
✓ Branch 0 taken 38710 times.
✓ Branch 1 taken 310612 times.
349357 }
8650
8651 /*
8652 Encapsulates the operations to be done before applying
8653 row events for update and delete.
8654
8655 @ret value error code
8656 0 success
8657 */
8658 38710 int Rows_log_event::row_operations_scan_and_key_setup() {
8659 38710 int error = 0;
8660
1/2
✓ Branch 0 taken 38710 times.
✗ Branch 1 not taken.
38710 DBUG_TRACE;
8661
8662 /*
8663 Prepare memory structures for search operations. If
8664 search is performed:
8665
8666 1. using hash search => initialize the hash
8667 2. using key => decide on key to use and allocate mem structures
8668 3. using table scan => do nothing
8669 */
8670
1/2
✓ Branch 0 taken 38710 times.
✗ Branch 1 not taken.
38710 decide_row_lookup_algorithm_and_key();
8671
8672
3/3
✓ Branch 0 taken 12348 times.
✓ Branch 1 taken 25684 times.
✓ Branch 2 taken 678 times.
38710 switch (m_rows_lookup_algorithm) {
8673 12348 case ROW_LOOKUP_HASH_SCAN: {
8674
2/4
✓ Branch 0 taken 12348 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12348 times.
12348 if (m_hash.init()) error = HA_ERR_OUT_OF_MEM;
8675 12348 goto err;
8676 }
8677 25684 case ROW_LOOKUP_INDEX_SCAN: {
8678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25684 times.
25684 assert(m_key_index < MAX_KEY);
8679 // Allocate buffer for key searches
8680
1/2
✓ Branch 0 taken 25684 times.
✗ Branch 1 not taken.
25684 m_key = (uchar *)my_malloc(key_memory_log_event, m_key_info->key_length,
8681 MYF(MY_WME));
8682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25684 times.
25684 if (!m_key) error = HA_ERR_OUT_OF_MEM;
8683 25684 goto err;
8684 }
8685 678 case ROW_LOOKUP_TABLE_SCAN:
8686 default:
8687 678 break;
8688 }
8689 38710 err:
8690 38710 return error;
8691 38710 }
8692
8693 /*
8694 Encapsulates the operations to be done after applying
8695 row events for update and delete.
8696
8697 @ret value error code
8698 0 success
8699 */
8700
8701 38707 int Rows_log_event::row_operations_scan_and_key_teardown(int error) {
8702
1/2
✓ Branch 0 taken 38707 times.
✗ Branch 1 not taken.
38707 DBUG_TRACE;
8703
8704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38707 times.
38707 assert(!m_table->file->inited);
8705
3/3
✓ Branch 0 taken 12348 times.
✓ Branch 1 taken 25681 times.
✓ Branch 2 taken 678 times.
38707 switch (m_rows_lookup_algorithm) {
8706 12348 case ROW_LOOKUP_HASH_SCAN: {
8707
1/2
✓ Branch 0 taken 12348 times.
✗ Branch 1 not taken.
12348 m_hash.deinit(); // we don't need the hash anymore.
8708 12348 goto err;
8709 }
8710
8711 25681 case ROW_LOOKUP_INDEX_SCAN: {
8712
1/2
✓ Branch 0 taken 25681 times.
✗ Branch 1 not taken.
25681 if (m_table->s->keys > 0) {
8713
1/2
✓ Branch 0 taken 25681 times.
✗ Branch 1 not taken.
25681 my_free(m_key); // Free for multi_malloc
8714 25681 m_key = nullptr;
8715 25681 m_key_index = MAX_KEY;
8716 25681 m_key_info = nullptr;
8717 }
8718 25681 goto err;
8719 }
8720
8721 678 case ROW_LOOKUP_TABLE_SCAN:
8722 default:
8723 678 break;
8724 }
8725
8726 38707 err:
8727 38707 m_rows_lookup_algorithm = ROW_LOOKUP_UNDEFINED;
8728 38707 return error;
8729 38707 }
8730
8731 3770511 bool Rows_log_event::is_auto_inc_in_extra_columns() {
8732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3770511 times.
3770511 assert(m_table);
8733
2/2
✓ Branch 0 taken 1147899 times.
✓ Branch 1 taken 2622612 times.
4918626 return (m_table->next_number_field &&
8734 1148008 this->m_fields.translate_position(
8735
2/2
✓ Branch 0 taken 748 times.
✓ Branch 1 taken 1147367 times.
6066741 m_table->next_number_field->field_index()) >= m_width);
8736 }
8737
8738 8 bool Rows_log_event::is_trx_retryable_upon_engine_error(int error) {
8739
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
8 return (error == HA_ERR_LOCK_DEADLOCK || error == HA_ERR_LOCK_WAIT_TIMEOUT);
8740 }
8741
8742 /*
8743 Compares table->record[0] and table->record[1]
8744
8745 Returns true if different.
8746 */
8747 20363 static bool record_compare(TABLE *table, MY_BITMAP *cols) {
8748
1/2
✓ Branch 0 taken 20363 times.
✗ Branch 1 not taken.
20363 DBUG_TRACE;
8749
8750 /*
8751 Need to set the X bit and the filler bits in both records since
8752 there are engines that do not set it correctly.
8753
8754 In addition, since MyISAM checks that one hasn't tampered with the
8755 record, it is necessary to restore the old bytes into the record
8756 after doing the comparison.
8757
8758 TODO[record format ndb]: Remove it once NDB returns correct
8759 records. Check that the other engines also return correct records.
8760 */
8761
8762
1/2
✓ Branch 0 taken 20363 times.
✗ Branch 1 not taken.
20363 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
8763
1/2
✓ Branch 0 taken 20363 times.
✗ Branch 1 not taken.
20363 DBUG_DUMP("record[1]", table->record[1], table->s->reclength);
8764
8765 20363 bool result = false;
8766 20363 uchar saved_x[2] = {0, 0}, saved_filler[2] = {0, 0};
8767
8768
1/2
✓ Branch 0 taken 20363 times.
✗ Branch 1 not taken.
20363 if (table->s->null_bytes > 0) {
8769
2/2
✓ Branch 0 taken 40726 times.
✓ Branch 1 taken 20363 times.
61089 for (int i = 0; i < 2; ++i) {
8770 /*
8771 If we have an X bit then we need to take care of it.
8772 */
8773
2/2
✓ Branch 0 taken 25274 times.
✓ Branch 1 taken 15452 times.
40726 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD)) {
8774 25274 saved_x[i] = table->record[i][0];
8775 25274 table->record[i][0] |= 1U;
8776 }
8777
8778 /*
8779 If (last_null_bit_pos == 0 && null_bytes > 1), then:
8780
8781 X bit (if any) + N nullable fields + M Field_bit fields = 8 bits
8782
8783 Ie, the entire byte is used.
8784 */
8785
2/2
✓ Branch 0 taken 39626 times.
✓ Branch 1 taken 1100 times.
40726 if (table->s->last_null_bit_pos > 0) {
8786 39626 saved_filler[i] = table->record[i][table->s->null_bytes - 1];
8787 39626 table->record[i][table->s->null_bytes - 1] |=
8788 39626 256U - (1U << table->s->last_null_bit_pos);
8789 }
8790 }
8791 }
8792
8793 /**
8794 Compare full record only if:
8795 - there are no blob fields (otherwise we would also need
8796 to compare blobs contents as well);
8797 - there are no varchar fields (otherwise we would also need
8798 to compare varchar contents as well);
8799 - there are no null fields, otherwise NULLed fields
8800 contents (i.e., the don't care bytes) may show arbitrary
8801 values, depending on how each engine handles internally.
8802 - if all the bitmap is set (both are full rows)
8803 */
8804 40726 if ((table->s->blob_fields + table->s->varchar_fields +
8805
4/4
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 20260 times.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 20277 times.
20466 table->s->null_fields) == 0 &&
8806
3/4
✓ Branch 0 taken 103 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 86 times.
✓ Branch 3 taken 17 times.
103 bitmap_is_set_all(cols)) {
8807 86 result = cmp_record(table, record[1]);
8808 }
8809
8810 /*
8811 Fallback to field-by-field comparison:
8812 1. start by checking if the field is signaled:
8813 2. if it is, first compare the null bit if the field is nullable
8814 3. then compare the contents of the field, if it is not
8815 set to null
8816 */
8817 else {
8818 100704 for (Field **ptr = table->field;
8819
7/8
✓ Branch 0 taken 80659 times.
✓ Branch 1 taken 20045 times.
✓ Branch 2 taken 80659 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 80427 times.
✓ Branch 5 taken 232 times.
✓ Branch 6 taken 80427 times.
✓ Branch 7 taken 20277 times.
100704 *ptr && ((*ptr)->field_index() < cols->n_bits) && !result; ptr++) {
8820 80427 Field *field = *ptr;
8821
4/4
✓ Branch 0 taken 75799 times.
✓ Branch 1 taken 4628 times.
✓ Branch 2 taken 75773 times.
✓ Branch 3 taken 4654 times.
156226 if (bitmap_is_set(cols, field->field_index()) &&
8822
2/2
✓ Branch 0 taken 75773 times.
✓ Branch 1 taken 26 times.
75799 !field->is_virtual_gcol()) {
8823 /* compare null bit */
8824
3/6
✓ Branch 0 taken 75773 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75773 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 75773 times.
75773 if (field->is_null() != field->is_null_in_record(table->record[1]))
8825 result = true;
8826
8827 /* compare content, only if fields are not set to NULL */
8828
3/4
✓ Branch 0 taken 75773 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 74786 times.
✓ Branch 3 taken 987 times.
75773 else if (!field->is_null())
8829
1/2
✓ Branch 0 taken 74786 times.
✗ Branch 1 not taken.
74786 result = field->cmp_binary_offset(table->s->rec_buff_length);
8830 }
8831 }
8832 }
8833
8834 /*
8835 Restore the saved bytes.
8836
8837 TODO[record format ndb]: Remove this code once NDB returns the
8838 correct record format.
8839 */
8840
1/2
✓ Branch 0 taken 20363 times.
✗ Branch 1 not taken.
20363 if (table->s->null_bytes > 0) {
8841
2/2
✓ Branch 0 taken 40726 times.
✓ Branch 1 taken 20363 times.
61089 for (int i = 0; i < 2; ++i) {
8842
2/2
✓ Branch 0 taken 25274 times.
✓ Branch 1 taken 15452 times.
40726 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD))
8843 25274 table->record[i][0] = saved_x[i];
8844
8845
2/2
✓ Branch 0 taken 39626 times.
✓ Branch 1 taken 1100 times.
40726 if (table->s->last_null_bit_pos)
8846 39626 table->record[i][table->s->null_bytes - 1] = saved_filler[i];
8847 }
8848 }
8849
8850 20363 return result;
8851 20363 }
8852
8853 3452342 void Rows_log_event::do_post_row_operations(Relay_log_info const *rli,
8854 int error) {
8855 /*
8856 If m_curr_row_end was not set during event execution (e.g., because
8857 of errors) we can't proceed to the next row. If the error is transient
8858 (i.e., error==0 at this point) we must call unpack_current_row() to set
8859 m_curr_row_end.
8860 */
8861
8862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3452420 times.
3452342 DBUG_PRINT("info", ("curr_row: %p; curr_row_end: %p; rows_end: %p",
8863 m_curr_row, m_curr_row_end, m_rows_end));
8864
8865
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3452375 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3452375 if (!m_curr_row_end && !error) {
8866 /*
8867 This function is always called immediately following a call to
8868 handle_idempotent_and_ignored_errors which returns 0. And
8869 handle_idempotent_and_ignored_errors can only return 0 when
8870 error==0. And when error==0, it means that the previous call to
8871 unpack_currrent_row was successful. And that means
8872 m_curr_row_end has been set to a valid pointer. So it is
8873 impossible that both error==0 and m_curr_row_end==0 under normal
8874 conditions. So this is probably a case of a corrupt event.
8875 */
8876 const uchar *previous_m_curr_row = m_curr_row;
8877 error = unpack_current_row(rli, &m_cols, true /*is AI*/);
8878
8879 if (!error && previous_m_curr_row == m_curr_row) {
8880 error = 1;
8881 }
8882 }
8883
8884 // at this moment m_curr_row_end should be set
8885
2/4
✓ Branch 0 taken 3452389 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3452389 times.
3452375 assert(error || m_curr_row_end != nullptr);
8886
3/4
✓ Branch 0 taken 3452366 times.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3452366 times.
3452375 assert(error || m_curr_row <= m_curr_row_end);
8887
3/4
✓ Branch 0 taken 3452369 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3452369 times.
3452375 assert(error || m_curr_row_end <= m_rows_end);
8888
8889 3452375 m_curr_row = m_curr_row_end;
8890
8891
5/6
✓ Branch 0 taken 3452375 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 392012 times.
✓ Branch 3 taken 3060401 times.
✓ Branch 4 taken 392009 times.
✓ Branch 5 taken 3060404 times.
3452375 if (error == 0 && !m_table->file->has_transactions()) {
8892 392009 thd->get_transaction()->set_unsafe_rollback_flags(Transaction_ctx::SESSION,
8893 true);
8894 392019 thd->get_transaction()->set_unsafe_rollback_flags(Transaction_ctx::STMT,
8895 true);
8896 }
8897
8898 #ifdef HAVE_PSI_STAGE_INTERFACE
8899 /*
8900 Count the number of rows processed unconditionally. Needed instrumentation
8901 may be toggled while a rows event is being processed.
8902 */
8903 3452446 m_psi_progress.inc_n_rows_applied(1);
8904
8905
2/2
✓ Branch 0 taken 3452385 times.
✓ Branch 1 taken 6 times.
3452391 if (m_curr_row > m_rows_buf) {
8906 /* Report progress. */
8907 3452385 m_psi_progress.update_work_estimated_and_completed(m_curr_row, m_rows_buf,
8908 3452385 m_rows_end);
8909
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 } else if (m_curr_row == m_rows_buf) {
8910 /*
8911 Master can generate an empty row, in the following situation:
8912 mysql> SET SESSION binlog_row_image=MINIMAL;
8913 mysql> CREATE TABLE t1 (c1 INT DEFAULT 100);
8914 mysql> INSERT INTO t1 VALUES ();
8915
8916 Otherwise, m_curr_row must be ahead of m_rows_buf, since we
8917 have processed the first row already.
8918
8919 No point in reporting progress, since this would show for a
8920 very small fraction of time - thence no point in speding extra
8921 CPU cycles for this.
8922
8923 Nevertheless assert that the event is a write event, otherwise,
8924 this should not happen.
8925 */
8926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(get_general_type_code() == binary_log::WRITE_ROWS_EVENT);
8927 } else
8928 /* Impossible */
8929 assert(false);
8930
8931
5/8
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 3452391 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 36 times.
3452448 DBUG_EXECUTE_IF("dbug.rpl_apply_sync_barrier", {
8932 const char act[] =
8933 "now SIGNAL signal.rpl_row_apply_progress_updated "
8934 "WAIT_FOR signal.rpl_row_apply_process_next_row";
8935 assert(opt_debug_sync_timeout > 0);
8936 assert(!debug_sync_set_action(thd, STRING_WITH_LEN(act)));
8937 };);
8938 #endif /* HAVE_PSI_STAGE_INTERFACE */
8939 3452427 }
8940
8941 3452736 int Rows_log_event::handle_idempotent_and_ignored_errors(
8942 Relay_log_info const *rli, int *err) {
8943 3452736 int error = *err;
8944
2/2
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 3452334 times.
3452736 if (error) {
8945 402 int actual_error = convert_handler_error(error, thd, m_table);
8946
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 269 times.
535 bool idempotent_error = (idempotent_error_code(error) &&
8947
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 104 times.
133 (rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT));
8948 bool ignored_error =
8949
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 29 times.
402 (idempotent_error == 0 ? ignored_error_code(actual_error) : 0);
8950
8951 #ifdef WITH_WSREP
8952 /* Check if error qualifies for WSREP ignore error condition (DML). */
8953
10/12
✓ Branch 0 taken 404 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 386 times.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 6 times.
✓ Branch 11 taken 397 times.
418 if (WSREP(thd) && !thd->slave_thread &&
8954
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 9 times.
15 wsrep_ignored_error_code(this, actual_error)) {
8955 6 idempotent_error = true;
8956 6 thd->wsrep_has_ignored_error = true;
8957 }
8958 #endif /* WITH_WSREP */
8959
8960
4/4
✓ Branch 0 taken 368 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 312 times.
403 if (idempotent_error || ignored_error) {
8961 loglevel ll;
8962
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 56 times.
91 if (idempotent_error)
8963 35 ll = WARNING_LEVEL;
8964 else
8965 56 ll = INFORMATION_LEVEL;
8966 91 slave_rows_error_report(
8967 ll, error, rli, thd, m_table, get_type_str(),
8968 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
8969 91 (ulong)common_header->log_pos);
8970 91 thd->get_stmt_da()->reset_condition_info(thd);
8971 91 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
8972 68 *err = 0;
8973
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 12 times.
68 if (idempotent_error == 0) return ignored_error;
8974 }
8975 }
8976
8977 3452658 return *err;
8978 }
8979
8980 3452441 int Rows_log_event::do_apply_row(Relay_log_info const *rli) {
8981
1/2
✓ Branch 0 taken 3452677 times.
✗ Branch 1 not taken.
3452441 DBUG_TRACE;
8982
8983 3452677 int error = 0;
8984
8985 /* in_use can have been set to NULL in close_tables_for_reopen */
8986 3452677 THD *old_thd = m_table->in_use;
8987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3452677 times.
3452677 if (!m_table->in_use) m_table->in_use = thd;
8988
8989
1/2
✓ Branch 0 taken 3452642 times.
✗ Branch 1 not taken.
3452677 error = do_exec_row(rli);
8990
8991
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 3452334 times.
3452642 if (error) {
8992
3/8
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 309 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
308 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
8993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 309 times.
309 assert(error != HA_ERR_RECORD_DELETED);
8994 }
8995 3452643 m_table->in_use = old_thd;
8996
8997 3452620 return error;
8998 3452643 }
8999
9000 /**
9001 Does the cleanup
9002 - closes the index if opened by open_record_scan
9003 - closes the table if opened for scanning.
9004 */
9005 645758 int Rows_log_event::close_record_scan() {
9006
1/2
✓ Branch 0 taken 645758 times.
✗ Branch 1 not taken.
645758 DBUG_TRACE;
9007 645758 int error = 0;
9008
9009 // if there is something to actually close
9010
2/2
✓ Branch 0 taken 638394 times.
✓ Branch 1 taken 7364 times.
645758 if (m_key_index < MAX_KEY) {
9011
3/4
✓ Branch 0 taken 193960 times.
✓ Branch 1 taken 444434 times.
✓ Branch 2 taken 193960 times.
✗ Branch 3 not taken.
638394 if (m_table->file->inited) error = m_table->file->ha_index_end();
9012
2/2
✓ Branch 0 taken 7361 times.
✓ Branch 1 taken 3 times.
7364 } else if (m_table->file->inited)
9013
1/2
✓ Branch 0 taken 7361 times.
✗ Branch 1 not taken.
7361 error = m_table->file->ha_rnd_end();
9014
9015 645758 return error;
9016 645758 }
9017
9018 214754 int Rows_log_event::next_record_scan(bool first_read) {
9019
1/2
✓ Branch 0 taken 214754 times.
✗ Branch 1 not taken.
214754 DBUG_TRACE;
9020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 214754 times.
214754 assert(m_table->file->inited);
9021 214754 TABLE *table = m_table;
9022 214754 int error = 0;
9023
9024
2/2
✓ Branch 0 taken 18438 times.
✓ Branch 1 taken 196316 times.
214754 if (m_key_index >= MAX_KEY)
9025
1/2
✓ Branch 0 taken 18438 times.
✗ Branch 1 not taken.
18438 error = table->file->ha_rnd_next(table->record[0]);
9026 else {
9027 /*
9028 We need to set the null bytes to ensure that the filler bit are
9029 all set when returning. There are storage engines that just set
9030 the necessary bits on the bytes and don't set the filler bits
9031 correctly.
9032 */
9033
1/2
✓ Branch 0 taken 196316 times.
✗ Branch 1 not taken.
196316 if (table->s->null_bytes > 0)
9034 196316 table->record[0][table->s->null_bytes - 1] |=
9035 196316 256U - (1U << table->s->last_null_bit_pos);
9036
9037
2/2
✓ Branch 0 taken 2356 times.
✓ Branch 1 taken 193960 times.
196316 if (!first_read) {
9038 /*
9039 if we fail to fetch next record corresponding to a key value, we
9040 move to the next key value. If we are out of key values as well an error
9041 will be returned.
9042 */
9043 4712 error = table->file->ha_index_next_same(table->record[0], m_key,
9044
1/2
✓ Branch 0 taken 2356 times.
✗ Branch 1 not taken.
2356 m_key_info->key_length);
9045
1/2
✓ Branch 0 taken 2356 times.
✗ Branch 1 not taken.
2356 if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN) {
9046 /*
9047 if we are out of rows for this particular key value, we reposition the
9048 marker according to the next key value that we have in the list.
9049 */
9050
2/2
✓ Branch 0 taken 2312 times.
✓ Branch 1 taken 44 times.
2356 if (error) {
9051
2/2
✓ Branch 0 taken 2309 times.
✓ Branch 1 taken 3 times.
2312 if (m_itr != m_distinct_keys.end()) {
9052 2309 m_key = *m_itr;
9053 2309 m_itr++;
9054 2309 first_read = true;
9055 } else {
9056
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 if (!is_trx_retryable_upon_engine_error(error))
9057 2 error = HA_ERR_KEY_NOT_FOUND;
9058 }
9059 }
9060 }
9061 }
9062
9063
2/2
✓ Branch 0 taken 196269 times.
✓ Branch 1 taken 47 times.
196316 if (first_read)
9064
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 196264 times.
196269 if ((error = table->file->ha_index_read_map(
9065
1/2
✓ Branch 0 taken 196269 times.
✗ Branch 1 not taken.
196269 table->record[0], m_key, HA_WHOLE_KEY, HA_READ_KEY_EXACT))) {
9066
3/8
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
5 DBUG_PRINT("info", ("no record matching the key found in the table"));
9067
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
5 if (!is_trx_retryable_upon_engine_error(error))
9068 4 error = HA_ERR_KEY_NOT_FOUND;
9069 }
9070 }
9071
9072 214754 return error;
9073 214754 }
9074
9075 /**
9076 Initializes scanning of rows. Opens an index and initializes an iterator
9077 over a list of distinct keys (m_distinct_keys) if it is a HASH_SCAN
9078 over an index or the table if its a HASH_SCAN over the table.
9079 */
9080 200543 int Rows_log_event::open_record_scan() {
9081 200543 int error = 0;
9082 200543 TABLE *table = m_table;
9083
1/2
✓ Branch 0 taken 200543 times.
✗ Branch 1 not taken.
200543 DBUG_TRACE;
9084
9085
2/2
✓ Branch 0 taken 193960 times.
✓ Branch 1 taken 6583 times.
200543 if (m_key_index < MAX_KEY) {
9086
2/2
✓ Branch 0 taken 5728 times.
✓ Branch 1 taken 188232 times.
193960 if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN) {
9087 /* initialize the iterator over the list of distinct keys that we have */
9088 5728 m_itr = m_distinct_keys.begin();
9089
9090 /* get the first element from the list of keys and increment the
9091 iterator
9092 */
9093 5728 m_key = *m_itr;
9094 5728 m_itr++;
9095 } else {
9096 /* this is an INDEX_SCAN we need to store the key in m_key */
9097
2/4
✓ Branch 0 taken 188232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 188232 times.
✗ Branch 3 not taken.
188232 assert((m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN) && m_key);
9098
1/2
✓ Branch 0 taken 188232 times.
✗ Branch 1 not taken.
188232 key_copy(m_key, m_table->record[0], m_key_info, 0);
9099 }
9100
9101 /*
9102 Save copy of the record in table->record[1]. It might be needed
9103 later if linear search is used to find exact match.
9104 */
9105 193960 store_record(table, record[1]);
9106
9107
3/8
✓ Branch 0 taken 193960 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 193960 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 193960 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
193960 DBUG_PRINT("info", ("locating record using a key (index_read)"));
9108
9109 /* The m_key_index'th key is active and usable: search the table using the
9110 * index */
9111
2/4
✓ Branch 0 taken 193960 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 193960 times.
387920 if (!table->file->inited &&
9112
2/4
✓ Branch 0 taken 193960 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 193960 times.
193960 (error = table->file->ha_index_init(m_key_index, false))) {
9113 DBUG_PRINT("info", ("ha_index_init returns error %d", error));
9114 goto end;
9115 }
9116
9117
1/2
✓ Branch 0 taken 193960 times.
✗ Branch 1 not taken.
193960 DBUG_DUMP("key data", m_key, m_key_info->key_length);
9118 } else {
9119
2/4
✓ Branch 0 taken 6583 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6583 times.
✗ Branch 3 not taken.
6583 if ((error = table->file->ha_rnd_init(true))) {
9120 DBUG_PRINT("info", ("error initializing table scan"
9121 " (ha_rnd_init returns %d)",
9122 error));
9123 table->file->print_error(error, MYF(0));
9124 }
9125 }
9126
9127 6583 end:
9128 200543 return error;
9129 200543 }
9130
9131 /**
9132 Populates the m_distinct_keys with unique keys to be modified
9133 during HASH_SCAN over keys.
9134 @retval 0 success
9135 */
9136 8062 int Rows_log_event::add_key_to_distinct_keyset() {
9137 8062 int error = 0;
9138
1/2
✓ Branch 0 taken 8062 times.
✗ Branch 1 not taken.
8062 DBUG_TRACE;
9139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8062 times.
8062 assert(m_key_index < MAX_KEY);
9140
1/2
✓ Branch 0 taken 8062 times.
✗ Branch 1 not taken.
8062 key_copy(m_distinct_key_spare_buf, m_table->record[0], m_key_info, 0);
9141 std::pair<std::set<uchar *, Key_compare>::iterator, bool> ret =
9142
1/2
✓ Branch 0 taken 8062 times.
✗ Branch 1 not taken.
8062 m_distinct_keys.insert(m_distinct_key_spare_buf);
9143
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 8040 times.
8062 if (ret.second) {
9144 /* Insert is successful, so allocate a new buffer for next key */
9145
1/2
✓ Branch 0 taken 8040 times.
✗ Branch 1 not taken.
8040 m_distinct_key_spare_buf = (uchar *)thd->alloc(m_key_info->key_length);
9146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8040 times.
8040 if (!m_distinct_key_spare_buf) {
9147 error = HA_ERR_OUT_OF_MEM;
9148 goto err;
9149 }
9150 }
9151
9152 22 err:
9153 8062 return error;
9154 8062 }
9155
9156 632669 int Rows_log_event::do_index_scan_and_update(Relay_log_info const *rli) {
9157
1/2
✓ Branch 0 taken 632669 times.
✗ Branch 1 not taken.
632669 DBUG_TRACE;
9158
2/4
✓ Branch 0 taken 632669 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 632669 times.
✗ Branch 3 not taken.
632669 assert(m_table && m_table->in_use != nullptr);
9159
9160 632669 int error = 0;
9161 632669 const uchar *saved_m_curr_row = m_curr_row;
9162
9163 /*
9164 rpl_row_tabledefs.test specifies that
9165 if the extra field on the slave does not have a default value
9166 and this is okay with Delete or Update events.
9167 Todo: fix wl3228 hld that requires defaults for all types of events
9168 */
9169
9170
1/2
✓ Branch 0 taken 632669 times.
✗ Branch 1 not taken.
632669 prepare_record(m_table, &this->m_local_cols, false);
9171
3/4
✓ Branch 0 taken 632669 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 632666 times.
632669 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) goto end;
9172
9173 /*
9174 Trying to do an index scan without a usable key
9175 This is a valid state because we allow the user
9176 to set Slave_rows_search_algorithm= 'INDEX_SCAN'.
9177
9178 Therefore on tables with no indexes we will end
9179 up here.
9180 */
9181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 632666 times.
632666 if (m_key_index >= MAX_KEY) {
9182 error = HA_ERR_END_OF_FILE;
9183 goto end;
9184 }
9185
9186 #ifndef NDEBUG
9187
3/8
✓ Branch 0 taken 632666 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 632666 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 632666 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
632666 DBUG_PRINT("info", ("looking for the following record"));
9188
1/2
✓ Branch 0 taken 632666 times.
✗ Branch 1 not taken.
632666 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
9189 #endif
9190
9191
2/2
✓ Branch 0 taken 1011 times.
✓ Branch 1 taken 631655 times.
632666 if (m_key_index != m_table->s->primary_key)
9192 /* we dont have a PK, or PK is not usable */
9193 1011 goto INDEX_SCAN;
9194
9195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 631655 times.
631655 if ((m_table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL)) {
9196 /*
9197 Read removal is possible since the engine supports write without
9198 previous read using full primary key
9199 */
9200 DBUG_PRINT("info", ("using read before write removal"));
9201 assert(m_key_index == m_table->s->primary_key);
9202
9203 /*
9204 Tell the handler to ignore if key exists or not, since it's
9205 not yet known if the key does exist(when using rbwr)
9206 */
9207 m_table->file->ha_extra(HA_EXTRA_IGNORE_NO_KEY);
9208
9209 goto end;
9210 }
9211
9212
2/2
✓ Branch 0 taken 444434 times.
✓ Branch 1 taken 187221 times.
631655 if ((m_table->file->ha_table_flags() &
9213 HA_PRIMARY_KEY_REQUIRED_FOR_POSITION)) {
9214 /*
9215 Use a more efficient method to fetch the record given by
9216 table->record[0] if the engine allows it. We first compute a
9217 row reference using the position() member function (it will be
9218 stored in table->file->ref) and then use rnd_pos() to position
9219 the "cursor" (i.e., record[0] in this case) at the correct row.
9220
9221 TODO: Check that the correct record has been fetched by
9222 comparing it with the original record. Take into account that the
9223 record on the master and slave can be of different
9224 length. Something along these lines should work:
9225
9226 ADD>>> store_record(table,record[1]);
9227 int error= table->file->rnd_pos(table->record[0],
9228 table->file->ref); ADD>>> assert(memcmp(table->record[1],
9229 table->record[0], table->s->reclength) == 0);
9230
9231 */
9232
9233
3/8
✓ Branch 0 taken 444434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 444434 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 444434 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
444434 DBUG_PRINT("info", ("locating record using primary key (position)"));
9234
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 444434 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 444434 times.
444434 if (m_table->file->inited && (error = m_table->file->ha_index_end()))
9235 goto end;
9236
9237
1/2
✓ Branch 0 taken 444434 times.
✗ Branch 1 not taken.
444434 error = m_table->file->rnd_pos_by_record(m_table->record[0]);
9238
9239
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 444402 times.
444434 if (error) {
9240
3/8
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
32 DBUG_PRINT("info", ("rnd_pos returns error %d", error));
9241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
9242 }
9243
9244 444434 goto end;
9245 }
9246
9247 // We can't use position() - try other methods.
9248
9249 187221 INDEX_SCAN:
9250
9251 /* Use the m_key_index'th key */
9252
9253
2/4
✓ Branch 0 taken 188232 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 188232 times.
188232 if ((error = open_record_scan())) goto end;
9254
9255
1/2
✓ Branch 0 taken 188232 times.
✗ Branch 1 not taken.
188232 error = next_record_scan(true);
9256
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 188231 times.
188232 if (error) {
9257
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1 DBUG_PRINT("info", ("no record matching the key found in the table"));
9258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
9259 1 goto end;
9260 }
9261
9262
3/8
✓ Branch 0 taken 188231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 188231 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 188231 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
188231 DBUG_PRINT("info", ("found first matching record"));
9263
1/2
✓ Branch 0 taken 188231 times.
✗ Branch 1 not taken.
188231 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
9264 /*
9265 Below is a minor "optimization". If the key (i.e., key number
9266 0) has the HA_NOSAME flag set, we know that we have found the
9267 correct record (since there can be no duplicates); otherwise, we
9268 have to compare the record with the one found to see if it is
9269 the correct one.
9270
9271 CAVEAT! This behaviour is essential for the replication of,
9272 e.g., the mysql.proc table since the correct record *shall* be
9273 found using the primary key *only*. There shall be no
9274 comparison of non-PK columns to decide if the correct record is
9275 found. I can see no scenario where it would be incorrect to
9276 chose the row to change only using a PK or an UNNI.
9277 */
9278
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 188219 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
188231 if (m_key_info->flags & HA_NOSAME || m_key_index == m_table->s->primary_key) {
9279 /* Unique does not have non nullable part */
9280
1/2
✓ Branch 0 taken 188219 times.
✗ Branch 1 not taken.
188219 if (!(m_key_info->flags & (HA_NULL_PART_KEY)))
9281 188219 goto end; // record found
9282 else {
9283 /*
9284 Unique has nullable part. We need to check if there is any field in the
9285 BI image that is null and part of UNNI.
9286 */
9287 bool null_found = false;
9288 for (uint i = 0; i < m_key_info->user_defined_key_parts && !null_found;
9289 i++) {
9290 uint fieldnr = m_key_info->key_part[i].fieldnr - 1;
9291 Field **f = m_table->field + fieldnr;
9292 null_found = (*f)->is_null();
9293 }
9294
9295 if (!null_found) goto end; // record found
9296
9297 /* else fall through to index scan */
9298 }
9299 }
9300
9301 /*
9302 In case key is not unique, we still have to iterate over records found
9303 and find the one which is identical to the row given. A copy of the
9304 record we are looking for is stored in record[1].
9305 */
9306
3/8
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12 DBUG_PRINT("info", ("non-unique index, scanning it to find matching record"));
9307
9308
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 while (record_compare(m_table, &this->m_local_cols)) {
9309 while ((error = next_record_scan(false))) {
9310 /* We just skip records that has already been deleted */
9311 if (error == HA_ERR_RECORD_DELETED) continue;
9312 DBUG_PRINT("info", ("no record matching the given row found"));
9313 goto end;
9314 }
9315 }
9316
9317 12 end:
9318
9319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 632669 times.
632669 assert(error != HA_ERR_RECORD_DELETED);
9320
9321
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 632633 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
632669 if (error && error != HA_ERR_RECORD_DELETED)
9322
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 m_table->file->print_error(error, MYF(0));
9323 else
9324
1/2
✓ Branch 0 taken 632630 times.
✗ Branch 1 not taken.
632633 error = do_apply_row(rli);
9325
9326
2/2
✓ Branch 0 taken 632581 times.
✓ Branch 1 taken 85 times.
632666 if (!error)
9327
1/2
✓ Branch 0 taken 632581 times.
✗ Branch 1 not taken.
632581 error = close_record_scan();
9328 else
9329 /*
9330 we are already with errors. Keep the error code and
9331 try to close the scan anyway.
9332 */
9333
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 (void)close_record_scan();
9334
9335
1/2
✓ Branch 0 taken 632666 times.
✗ Branch 1 not taken.
632666 int unpack_error = skip_after_image_for_update_event(rli, saved_m_curr_row);
9336
2/2
✓ Branch 0 taken 632581 times.
✓ Branch 1 taken 85 times.
632666 if (!error) error = unpack_error;
9337
9338 632666 m_table->default_column_bitmaps();
9339 632666 return error;
9340 632666 }
9341
9342 595769 int Update_rows_log_event::skip_after_image_for_update_event(
9343 const Relay_log_info *rli, const uchar *curr_bi_start) {
9344
4/4
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 595748 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 6 times.
595769 if (m_curr_row == curr_bi_start && m_curr_row_end != nullptr) {
9345 /*
9346 This handles the case that the BI was read successfully, but an
9347 error happened while looking up the row. In this case, the AI
9348 has not been read, so the read position is between the two
9349 images. In case the error is idempotent, we need to move the
9350 position to the end of the row, and therefore we skip past the
9351 AI.
9352
9353 The normal behavior is:
9354
9355 When unpack_row reads a row image, and there is no error,
9356 unpack_row sets m_curr_row_end to point to the end of the image,
9357 and leaves m_curr_row to point at the beginning.
9358
9359 The AI is read from Update_rows_log_event::do_exec_row. Before
9360 calling unpack_row, do_exec_row sets m_curr_row=m_curr_row_end,
9361 so that it actually reads the AI. And again, if there is no
9362 error, unpack_row sets m_curr_row_end to point to the end of the
9363 AI.
9364
9365 Thus, the positions are moved as follows:
9366
9367 +--------------+--------------+
9368 | BI | AI | NULL
9369 +--------------+--------------+
9370 0. Initial values ^m_curr_row ^m_curr_row_end
9371 1. Read BI, no error
9372 ^m_curr_row ^m_curr_row_end
9373 2. Lookup BI
9374 3. Set m_curr_row
9375 ^m_curr_row
9376 ^m_curr_row_end
9377 4. Read AI, no error
9378 ^m_curr_row ^m_curr_row_end
9379
9380 If an error happened while reading the BI (e.g. corruption),
9381 then we should not try to read the AI here. Therefore we do not
9382 read the AI if m_curr_row_end==NULL.
9383
9384 If an error happened while looking up BI, then we should try to
9385 read AI here. Then we know m_curr_row_end points to beginning of
9386 AI, so we come here, set m_curr_row=m_curr_row_end, and read the
9387 AI.
9388
9389 If an error happened while reading the AI, then we should not
9390 try to read the AI again. Therefore we do not read the AI if
9391 m_curr_row==curr_bi_start.
9392 */
9393 15 m_curr_row = m_curr_row_end;
9394 15 return unpack_current_row(rli, &m_cols_ai, true /*is AI*/,
9395 15 true /*only_seek*/);
9396 }
9397 595754 return 0;
9398 }
9399
9400 19356 int Rows_log_event::do_hash_row(Relay_log_info const *rli) {
9401
1/2
✓ Branch 0 taken 19356 times.
✗ Branch 1 not taken.
19356 DBUG_TRACE;
9402
2/4
✓ Branch 0 taken 19356 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19356 times.
✗ Branch 3 not taken.
19356 assert(m_table && m_table->in_use != nullptr);
9403 19356 int error = 0;
9404
9405 /* create an empty entry to add to the hash table */
9406
1/2
✓ Branch 0 taken 19356 times.
✗ Branch 1 not taken.
19356 HASH_ROW_ENTRY *entry = m_hash.make_entry();
9407
9408 /* Prepare the record, unpack and save positions. */
9409 19356 entry->positions->bi_start = m_curr_row; // save the bi start pos
9410
1/2
✓ Branch 0 taken 19356 times.
✗ Branch 1 not taken.
19356 prepare_record(m_table, &this->m_local_cols, false);
9411
3/4
✓ Branch 0 taken 19356 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 19353 times.
19356 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) {
9412 hash_slave_rows_free_entry freer;
9413
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 freer(entry);
9414 3 goto end;
9415 }
9416 19353 entry->positions->bi_ends = m_curr_row_end; // save the bi end pos
9417
9418 /*
9419 Now that m_table->record[0] is filled in, we can add the entry
9420 to the hash table. Note that the put operation calculates the
9421 key based on record[0] contents (including BLOB fields).
9422 */
9423
1/2
✓ Branch 0 taken 19353 times.
✗ Branch 1 not taken.
19353 m_hash.put(m_table, &this->m_local_cols, entry);
9424
9425
3/4
✓ Branch 0 taken 8062 times.
✓ Branch 1 taken 11291 times.
✓ Branch 2 taken 8062 times.
✗ Branch 3 not taken.
19353 if (m_key_index < MAX_KEY) add_key_to_distinct_keyset();
9426
9427 /*
9428 We need to unpack the AI to advance the positions, so we
9429 know when we have reached m_rows_end and that we do not
9430 unpack the AI in the next iteration as if it was a BI.
9431 */
9432
3/4
✓ Branch 0 taken 19353 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4848 times.
✓ Branch 3 taken 14505 times.
19353 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
9433 /* Save a copy of the BI. */
9434 14505 store_record(m_table, record[1]);
9435
9436 /*
9437 This is the situation after hashing the BI:
9438
9439 ===|=== before image ====|=== after image ===|===
9440 ^ ^
9441 m_curr_row m_curr_row_end
9442 */
9443
9444 /* Set the position to the start of the record to be unpacked. */
9445 14505 m_curr_row = m_curr_row_end;
9446
9447 /* We shouldn't need this, but lets not leave loose ends */
9448
1/2
✓ Branch 0 taken 14505 times.
✗ Branch 1 not taken.
14505 prepare_record(m_table, &this->m_local_cols, false);
9449 error =
9450
1/2
✓ Branch 0 taken 14505 times.
✗ Branch 1 not taken.
14505 unpack_current_row(rli, &m_cols_ai, true /*is AI*/, true /*only_seek*/);
9451
9452 /*
9453 This is the situation after unpacking the AI:
9454
9455 ===|=== before image ====|=== after image ===|===
9456 ^ ^
9457 m_curr_row m_curr_row_end
9458 */
9459
9460 /* Restore back the copy of the BI. */
9461 14505 restore_record(m_table, record[1]);
9462 }
9463
9464 4848 end:
9465 19356 return error;
9466 19356 }
9467
9468 12311 int Rows_log_event::do_scan_and_update(Relay_log_info const *rli) {
9469
1/2
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
12311 DBUG_TRACE;
9470
2/4
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12311 times.
✗ Branch 3 not taken.
12311 assert(m_table && m_table->in_use != nullptr);
9471
2/4
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12311 times.
12311 assert(m_hash.is_empty() == false);
9472 12311 TABLE *table = m_table;
9473 12311 int error = 0;
9474 12311 const uchar *saved_last_m_curr_row = nullptr;
9475 12311 const uchar *saved_last_m_curr_row_end = nullptr;
9476 /* create an empty entry to add to the hash table */
9477 12311 HASH_ROW_ENTRY *entry = nullptr;
9478 12311 int idempotent_errors = 0;
9479 12311 int i = 0;
9480
9481 12311 saved_last_m_curr_row = m_curr_row;
9482 12311 saved_last_m_curr_row_end = m_curr_row_end;
9483
9484
3/10
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12311 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12311 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
12311 DBUG_PRINT("info", ("Hash was populated with %d records!", m_hash.size()));
9485
9486 /* open table or index depending on whether we have set m_key_index or not. */
9487
2/4
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12311 times.
12311 if ((error = open_record_scan())) goto err;
9488
9489 /*
9490 Scan the table only once and compare against entries in hash.
9491 When a match is found, apply the changes.
9492 */
9493 do {
9494 /* get the next record from the table */
9495
1/2
✓ Branch 0 taken 26522 times.
✗ Branch 1 not taken.
26522 error = next_record_scan(i == 0);
9496 26522 i++;
9497
9498
5/10
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 26415 times.
✓ Branch 2 taken 107 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 107 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 107 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
26522 if (error) DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
9499
4/4
✓ Branch 0 taken 26415 times.
✓ Branch 1 taken 89 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 13 times.
26522 switch (error) {
9500 26415 case 0: {
9501
1/2
✓ Branch 0 taken 26415 times.
✗ Branch 1 not taken.
26415 entry = m_hash.get(table, &this->m_local_cols);
9502 /**
9503 The do..while loop takes care of the scenario of same row being
9504 updated more than once within a single Update_rows_log_event by
9505 performing the hash lookup for the updated_row(by taking the AI stored
9506 in table->record[0] after the ha_update_row()) when table has no
9507 primary key.
9508
9509 This can happen when update is called from a stored function.
9510 Ex:
9511 CREATE FUNCTION f1 () RETURNS INT BEGIN
9512 UPDATE t1 SET a = 2 WHERE a = 1;
9513 UPDATE t1 SET a = 3 WHERE a = 2;
9514 RETURN 0;
9515 END
9516 */
9517 do {
9518 26438 store_record(table, record[1]);
9519
9520 /**
9521 If there are collisions we need to be sure that this is
9522 indeed the record we want. Loop through all records for
9523 the given key and explicitly compare them against the
9524 record we got from the storage engine.
9525 */
9526
2/2
✓ Branch 0 taken 19330 times.
✓ Branch 1 taken 7108 times.
26438 while (entry) {
9527 19330 m_curr_row = entry->positions->bi_start;
9528 19330 m_curr_row_end = entry->positions->bi_ends;
9529
9530
1/2
✓ Branch 0 taken 19330 times.
✗ Branch 1 not taken.
19330 prepare_record(table, &this->m_local_cols, false);
9531
2/4
✓ Branch 0 taken 19330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19330 times.
19330 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/)))
9532 goto close_table;
9533
9534
2/4
✓ Branch 0 taken 19330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19330 times.
19330 if (record_compare(table, &this->m_local_cols))
9535 m_hash.next(&entry);
9536 else
9537 19330 break; // we found a match
9538 }
9539
9540 /**
9541 We found the entry we needed, just apply the changes.
9542 */
9543
2/2
✓ Branch 0 taken 19330 times.
✓ Branch 1 taken 7108 times.
26438 if (entry) {
9544 // just to be safe, copy the record from the SE to table->record[0]
9545 19330 restore_record(table, record[1]);
9546
9547 /**
9548 At this point, both table->record[0] and
9549 table->record[1] have the SE row that matched the one
9550 in the hash table.
9551
9552 Thence if this is a DELETE we wouldn't need to mess
9553 around with positions anymore, but since this can be an
9554 update, we need to provide positions so that AI is
9555 unpacked correctly to table->record[0] in UPDATE
9556 implementation of do_exec_row().
9557 */
9558 19330 m_curr_row = entry->positions->bi_start;
9559 19330 m_curr_row_end = entry->positions->bi_ends;
9560
9561 /* we don't need this entry anymore, just delete it */
9562
2/4
✓ Branch 0 taken 19330 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 19330 times.
19330 if ((error = m_hash.del(entry))) goto err;
9563
9564
3/4
✓ Branch 0 taken 19330 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 19288 times.
19330 if ((error = do_apply_row(rli))) {
9565
3/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 1 times.
42 if (handle_idempotent_and_ignored_errors(rli, &error))
9566 41 goto close_table;
9567
9568
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 do_post_row_operations(rli, error);
9569 }
9570 }
9571
1/2
✓ Branch 0 taken 26397 times.
✗ Branch 1 not taken.
26397 } while (this->get_general_type_code() ==
9572 21153 binary_log::UPDATE_ROWS_EVENT &&
9573
6/6
✓ Branch 0 taken 21153 times.
✓ Branch 1 taken 5244 times.
✓ Branch 2 taken 20020 times.
✓ Branch 3 taken 1133 times.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 26374 times.
46417 table->s->primary_key >= MAX_KEY &&
9574
3/4
✓ Branch 0 taken 20020 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 19997 times.
20020 (entry = m_hash.get(table, &m_cols)));
9575 26374 } break;
9576
9577 89 case HA_ERR_RECORD_DELETED:
9578 // get next
9579 89 continue;
9580
9581 5 case HA_ERR_KEY_NOT_FOUND:
9582 /* If the slave exec mode is idempotent or the error is
9583 skipped error, then don't break */
9584
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
5 if (handle_idempotent_and_ignored_errors(rli, &error)) goto close_table;
9585 3 idempotent_errors++;
9586 3 continue;
9587
9588 13 case HA_ERR_END_OF_FILE:
9589 default:
9590 // exception (hash is not empty and we have reached EOF or
9591 // other error happened)
9592 13 goto close_table;
9593 }
9594 }
9595 /**
9596 if the rbr_exec_mode is set to Idempotent, we cannot expect the hash to
9597 be empty. In such cases we count the number of idempotent errors and check
9598 if it is equal to or greater than the number of rows left in the hash.
9599 */
9600
7/10
✓ Branch 0 taken 26466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14211 times.
✓ Branch 3 taken 12255 times.
✓ Branch 4 taken 14211 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14211 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14211 times.
✓ Branch 9 taken 12255 times.
40677 while (((idempotent_errors < m_hash.size()) && !m_hash.is_empty()) &&
9601
3/4
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 14122 times.
✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
14211 (!error || (error == HA_ERR_RECORD_DELETED)));
9602
9603 12255 close_table:
9604
3/10
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12311 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12311 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
12311 DBUG_PRINT("info", ("m_hash.size()=%d error=%d idempotent_errors=%d",
9605 m_hash.size(), error, idempotent_errors));
9606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12311 times.
12311 if (error == HA_ERR_RECORD_DELETED) error = 0;
9607
9608
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 12269 times.
12311 if (error) {
9609
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 table->file->print_error(error, MYF(0));
9610
3/8
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
42 DBUG_PRINT("info", ("Failed to get next record"
9611 " (ha_rnd_next returns %d)",
9612 error));
9613 /*
9614 we are already with errors. Keep the error code and
9615 try to close the scan anyway.
9616 */
9617
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 (void)close_record_scan();
9618 } else
9619
1/2
✓ Branch 0 taken 12269 times.
✗ Branch 1 not taken.
12269 error = close_record_scan();
9620
9621 12311 err:
9622
9623
10/12
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12293 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 12266 times.
✓ Branch 6 taken 45 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 30 times.
✓ Branch 9 taken 15 times.
✓ Branch 10 taken 12296 times.
✓ Branch 11 taken 15 times.
12311 if ((m_hash.is_empty() && !error) || (idempotent_errors >= m_hash.size())) {
9624 /**
9625 Reset the last positions, because the positions are lost while
9626 handling entries in the hash.
9627 */
9628 12296 m_curr_row = saved_last_m_curr_row;
9629 12296 m_curr_row_end = saved_last_m_curr_row_end;
9630 }
9631
9632 12311 return error;
9633 12311 }
9634
9635 19356 int Rows_log_event::do_hash_scan_and_update(Relay_log_info const *rli) {
9636
1/2
✓ Branch 0 taken 19356 times.
✗ Branch 1 not taken.
19356 DBUG_TRACE;
9637
2/4
✓ Branch 0 taken 19356 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19356 times.
✗ Branch 3 not taken.
19356 assert(m_table && m_table->in_use != nullptr);
9638
9639 // HASHING PART
9640
9641 /* unpack the BI (and AI, if it exists) and add it to the hash map. */
9642
3/4
✓ Branch 0 taken 19356 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 19353 times.
19356 if (int error = this->do_hash_row(rli)) return error;
9643
9644 /* We have not yet hashed all rows in the buffer. Do not proceed to the SCAN
9645 * part. */
9646
2/2
✓ Branch 0 taken 7042 times.
✓ Branch 1 taken 12311 times.
19353 if (m_curr_row_end < m_rows_end) return 0;
9647
9648
3/10
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12311 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12311 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
12311 DBUG_PRINT("info", ("Hash was populated with %d records!", m_hash.size()));
9649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12311 times.
12311 assert(m_curr_row_end == m_rows_end);
9650
9651 // SCANNING & UPDATE PART
9652
9653
1/2
✓ Branch 0 taken 12311 times.
✗ Branch 1 not taken.
12311 return this->do_scan_and_update(rli);
9654 19356 }
9655
9656 781 int Rows_log_event::do_table_scan_and_update(Relay_log_info const *rli) {
9657 781 int error = 0;
9658 781 const uchar *saved_m_curr_row = m_curr_row;
9659 781 TABLE *table = m_table;
9660
9661
1/2
✓ Branch 0 taken 781 times.
✗ Branch 1 not taken.
781 DBUG_TRACE;
9662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 781 times.
781 assert(m_curr_row != m_rows_end);
9663
3/8
✓ Branch 0 taken 781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 781 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 781 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
781 DBUG_PRINT("info", ("locating record using table scan (ha_rnd_next)"));
9664
9665 781 saved_m_curr_row = m_curr_row;
9666
9667 /** unpack the before image */
9668
1/2
✓ Branch 0 taken 781 times.
✗ Branch 1 not taken.
781 prepare_record(table, &this->m_local_cols, false);
9669
3/4
✓ Branch 0 taken 781 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 778 times.
781 if (!(error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) {
9670 /** save a copy so that we can compare against it later */
9671 778 store_record(m_table, record[1]);
9672
9673 778 int restart_count = 0; // Number of times scanning has restarted from top
9674
9675
2/4
✓ Branch 0 taken 778 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 778 times.
778 if ((error = m_table->file->ha_rnd_init(true))) {
9676 DBUG_PRINT("info", ("error initializing table scan"
9677 " (ha_rnd_init returns %d)",
9678 error));
9679 goto end;
9680 }
9681
9682 /* Continue until we find the right record or have made a full loop */
9683 do {
9684 778 restart_ha_rnd_next:
9685
1/2
✓ Branch 0 taken 1030 times.
✗ Branch 1 not taken.
1030 error = m_table->file->ha_rnd_next(m_table->record[0]);
9686
5/10
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1021 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1030 if (error) DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
9687
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1021 times.
✓ Branch 3 taken 1 times.
1030 switch (error) {
9688 8 case HA_ERR_END_OF_FILE:
9689 // restart scan from top
9690
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (++restart_count < 2) {
9691
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if ((error = m_table->file->ha_rnd_init(true))) goto end;
9692 4 goto restart_ha_rnd_next;
9693 }
9694 4 break;
9695
9696 case HA_ERR_RECORD_DELETED:
9697 // fetch next
9698 goto restart_ha_rnd_next;
9699 1021 case 0:
9700 // we're good, check if record matches
9701 1021 break;
9702
9703 1 default:
9704 // exception
9705 1 goto end;
9706 }
9707
7/8
✓ Branch 0 taken 1021 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1021 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 248 times.
✓ Branch 5 taken 773 times.
✓ Branch 6 taken 248 times.
✓ Branch 7 taken 777 times.
1025 } while (restart_count < 2 && record_compare(m_table, &this->m_local_cols));
9708 }
9709
9710 3 end:
9711
9712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 781 times.
781 assert(error != HA_ERR_RECORD_DELETED);
9713
9714 /* either we report error or apply the changes */
9715
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 773 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
781 if (error && error != HA_ERR_RECORD_DELETED) {
9716
3/8
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8 DBUG_PRINT("info", ("Failed to get next record"
9717 " (ha_rnd_next returns %d)",
9718 error));
9719
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 m_table->file->print_error(error, MYF(0));
9720 } else
9721
1/2
✓ Branch 0 taken 773 times.
✗ Branch 1 not taken.
773 error = do_apply_row(rli);
9722
9723
2/2
✓ Branch 0 taken 731 times.
✓ Branch 1 taken 50 times.
781 if (!error)
9724
1/2
✓ Branch 0 taken 731 times.
✗ Branch 1 not taken.
731 error = close_record_scan();
9725 else
9726 /*
9727 we are already with errors. Keep the error code and
9728 try to close the scan anyway.
9729 */
9730
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 (void)close_record_scan();
9731
9732
1/2
✓ Branch 0 taken 781 times.
✗ Branch 1 not taken.
781 int unpack_error = skip_after_image_for_update_event(rli, saved_m_curr_row);
9733
2/2
✓ Branch 0 taken 731 times.
✓ Branch 1 taken 50 times.
781 if (!error) error = unpack_error;
9734
9735 781 table->default_column_bitmaps();
9736 781 return error;
9737 781 }
9738
9739 351673 int Rows_log_event::do_apply_event(Relay_log_info const *rli) {
9740
1/2
✓ Branch 0 taken 351860 times.
✗ Branch 1 not taken.
351673 DBUG_TRACE;
9741 351860 TABLE *table = nullptr;
9742 351860 int error = 0;
9743
9744 /*
9745 'thd' has been set by exec_relay_log_event(), just before calling
9746 do_apply_event(). We still check here to prevent future coding
9747 errors.
9748 */
9749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 351860 times.
351860 assert(rli->info_thd == thd);
9750
9751 /*
9752 If there is no locks taken, this is the first binrow event seen
9753 after the table map events. We should then lock all the tables
9754 used in the transaction and proceed with execution of the actual
9755 event.
9756 */
9757
2/2
✓ Branch 0 taken 299618 times.
✓ Branch 1 taken 52242 times.
351860 if (!thd->lock) {
9758 /*
9759 Lock_tables() reads the contents of thd->lex, so they must be
9760 initialized.
9761
9762 We also call the mysql_reset_thd_for_next_command(), since this
9763 is the logical start of the next "statement". Note that this
9764 call might reset the value of current_stmt_binlog_format, so
9765 we need to do any changes to that value after this function.
9766 */
9767
1/2
✓ Branch 0 taken 299768 times.
✗ Branch 1 not taken.
299618 lex_start(thd);
9768
1/2
✓ Branch 0 taken 299763 times.
✗ Branch 1 not taken.
299768 mysql_reset_thd_for_next_command(thd);
9769
9770
1/2
✓ Branch 0 taken 299766 times.
✗ Branch 1 not taken.
299763 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
9771
2/2
✓ Branch 0 taken 297841 times.
✓ Branch 1 taken 1925 times.
299766 if (state == GTID_STATEMENT_EXECUTE) {
9772
2/4
✓ Branch 0 taken 297802 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 297802 times.
297841 if (gtid_pre_statement_post_implicit_commit_checks(thd))
9773 state = GTID_STATEMENT_CANCEL;
9774 }
9775
9776
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 299725 times.
299727 if (state == GTID_STATEMENT_CANCEL) {
9777 2 uint mysql_error = thd->get_stmt_da()->mysql_errno();
9778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(mysql_error != 0);
9779
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report(ERROR_LEVEL, mysql_error, "Error executing row event: '%s'",
9780 2 thd->get_stmt_da()->message_text());
9781 2 thd->is_slave_error = true;
9782 270 return -1;
9783
2/2
✓ Branch 0 taken 1926 times.
✓ Branch 1 taken 297799 times.
299725 } else if (state == GTID_STATEMENT_SKIP)
9784 1930 goto end;
9785
9786 /*
9787 The current statement is just about to begin and
9788 has not yet modified anything. Note, all.modified is reset
9789 by mysql_reset_thd_for_next_command.
9790 */
9791
1/2
✓ Branch 0 taken 297802 times.
✗ Branch 1 not taken.
297799 thd->get_transaction()->reset_unsafe_rollback_flags(Transaction_ctx::STMT);
9792 /*
9793 This is a row injection, so we flag the "statement" as
9794 such. Note that this code is called both when the slave does row
9795 injections and when the BINLOG statement is used to do row
9796 injections.
9797 */
9798
1/2
✓ Branch 0 taken 297790 times.
✗ Branch 1 not taken.
297802 thd->lex->set_stmt_row_injection();
9799
9800 /*
9801 There are a few flags that are replicated with each row event.
9802 Make sure to set/clear them before executing the main body of
9803 the event.
9804 */
9805
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 297667 times.
297790 if (get_flags(NO_FOREIGN_KEY_CHECKS_F))
9806 76 thd->variables.option_bits |= OPTION_NO_FOREIGN_KEY_CHECKS;
9807 else
9808 297667 thd->variables.option_bits &= ~OPTION_NO_FOREIGN_KEY_CHECKS;
9809
9810
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 297783 times.
297743 if (get_flags(RELAXED_UNIQUE_CHECKS_F))
9811 4 thd->variables.option_bits |= OPTION_RELAXED_UNIQUE_CHECKS;
9812 else
9813 297783 thd->variables.option_bits &= ~OPTION_RELAXED_UNIQUE_CHECKS;
9814
9815 297787 thd->binlog_row_event_extra_data = m_extra_row_info.get_ndb_info();
9816
9817 /* A small test to verify that objects have consistent types */
9818 assert(sizeof(thd->variables.option_bits) ==
9819 sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
9820
2/8
✓ Branch 0 taken 297775 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 297775 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
297758 DBUG_EXECUTE_IF("rows_log_event_before_open_table", {
9821 const char action[] =
9822 "now SIGNAL before_open_table WAIT_FOR go_ahead_sql";
9823 assert(!debug_sync_set_action(thd, STRING_WITH_LEN(action)));
9824 };);
9825
3/4
✓ Branch 0 taken 297669 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 297660 times.
297775 if (open_and_lock_tables(thd, rli->tables_to_lock, 0)) {
9826 #ifdef WITH_WSREP
9827
2/8
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9 if (WSREP(thd)) {
9828 WSREP_WARN(
9829 "BF applier failed to open_and_lock_tables: %u, fatal: %s "
9830 "wsrep = (exec_mode: %s conflict_state: %s seqno: %lld) ",
9831 thd->get_stmt_da()->mysql_errno(),
9832 thd->is_fatal_error() ? "true" : "false",
9833 wsrep_thd_client_mode_str(thd),
9834 wsrep_thd_transaction_state_str(thd),
9835 (long long)wsrep_thd_trx_seqno(thd));
9836 }
9837 #endif /* WITH_WSREP */
9838
9839
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 if (thd->is_error()) {
9840 9 uint actual_error = thd->get_stmt_da()->mysql_errno();
9841
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7 times.
9 if (ignored_error_code(actual_error)) {
9842
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (log_error_verbosity >= 2)
9843
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 rli->report(WARNING_LEVEL, actual_error,
9844 "Error executing row event: '%s'",
9845 2 thd->get_stmt_da()->message_text());
9846
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->get_stmt_da()->reset_condition_info(thd);
9847
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
9848 2 error = 0;
9849 2 goto end;
9850 } else {
9851
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 rli->report(ERROR_LEVEL, actual_error,
9852 "Error executing row event: '%s'",
9853 7 thd->get_stmt_da()->message_text());
9854 7 thd->is_slave_error = true;
9855 }
9856 }
9857 7 return 1;
9858 }
9859
9860 /*
9861 When the open and locking succeeded, we check all tables to
9862 ensure that they still have the correct type.
9863 */
9864
9865 {
9866
3/8
✓ Branch 0 taken 297619 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 297778 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 297778 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
297660 DBUG_PRINT("debug",
9867 ("Checking compability of tables to lock - tables_to_lock: %p",
9868 rli->tables_to_lock));
9869
9870 /**
9871 When using RBR and MyISAM MERGE tables the base tables that make
9872 up the MERGE table can be appended to the list of tables to lock.
9873
9874 Thus, we just check compatibility for those that tables that have
9875 a correspondent table map event (ie, those that are actually going
9876 to be accessed while applying the event). That's why the loop stops
9877 at rli->tables_to_lock_count .
9878
9879 NOTE: The base tables are added here are removed when
9880 close_thread_tables is called.
9881 */
9882 297780 TABLE_LIST *table_list_ptr = rli->tables_to_lock;
9883
3/4
✓ Branch 0 taken 298727 times.
✓ Branch 1 taken 297682 times.
✓ Branch 2 taken 298773 times.
✗ Branch 3 not taken.
596409 for (uint i = 0; table_list_ptr && (i < rli->tables_to_lock_count);
9884 298629 table_list_ptr = table_list_ptr->next_global, i++) {
9885 /*
9886 Below if condition takes care of skipping base tables that
9887 make up the MERGE table (which are added by open_tables()
9888 call). They are added next to the merge table in the list.
9889 For eg: If RPL_TABLE_LIST is t3->t1->t2 (where t1 and t2
9890 are base tables for merge table 't3'), open_tables will modify
9891 the list by adding t1 and t2 again immediately after t3 in the
9892 list (*not at the end of the list*). New table_to_lock list will
9893 look like t3->t1'->t2'->t1->t2 (where t1' and t2' are TABLE_LIST
9894 objects added by open_tables() call). There is no flag(or logic) in
9895 open_tables() that can skip adding these base tables to the list.
9896 So the logic here should take care of skipping them.
9897
9898 tables_to_lock_count logic will take care of skipping base tables
9899 that are added at the end of the list.
9900 For eg: If RPL_TABLE_LIST is t1->t2->t3, open_tables will modify
9901 the list into t1->t2->t3->t1'->t2'. t1' and t2' will be skipped
9902 because tables_to_lock_count logic in this for loop.
9903 */
9904
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 298773 times.
298773 if (table_list_ptr->parent_l) continue;
9905 /*
9906 We can use a down cast here since we know that every table added
9907 to the tables_to_lock is a RPL_TABLE_LIST (or child table which is
9908 skipped above).
9909 */
9910 298773 RPL_TABLE_LIST *ptr = static_cast<RPL_TABLE_LIST *>(table_list_ptr);
9911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 298773 times.
298773 assert(ptr->m_tabledef_valid);
9912 TABLE *conv_table;
9913
3/4
✓ Branch 0 taken 298783 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
✓ Branch 3 taken 298526 times.
298773 if (!ptr->m_tabledef.compatible_with(thd,
9914 const_cast<Relay_log_info *>(rli),
9915 ptr->table, &conv_table)) {
9916
3/8
✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 257 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
257 DBUG_PRINT("debug",
9917 ("Table: %s.%s is not compatible with master",
9918 ptr->table->s->db.str, ptr->table->s->table_name.str));
9919
2/2
✓ Branch 0 taken 255 times.
✓ Branch 1 taken 2 times.
257 if (thd->is_slave_error) {
9920
1/2
✓ Branch 0 taken 255 times.
✗ Branch 1 not taken.
255 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
9921 255 return ERR_BAD_TABLE_DEF;
9922 } else {
9923
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->get_stmt_da()->reset_condition_info(thd);
9924
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
9925 2 error = 0;
9926 2 goto end;
9927 }
9928 }
9929
3/8
✓ Branch 0 taken 298514 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 298626 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 298626 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
298526 DBUG_PRINT("debug", ("Table: %s.%s is compatible with master"
9930 " - conv_table: %p",
9931 ptr->table->s->db.str,
9932 ptr->table->s->table_name.str, conv_table));
9933 298629 ptr->m_conv_table = conv_table;
9934 }
9935 }
9936
9937 /*
9938 ... and then we add all the tables to the table map and but keep
9939 them in the tables to lock list.
9940 */
9941 297636 TABLE_LIST *ptr = rli->tables_to_lock;
9942
4/4
✓ Branch 0 taken 298615 times.
✓ Branch 1 taken 297706 times.
✓ Branch 2 taken 298611 times.
✓ Branch 3 taken 4 times.
596321 for (uint i = 0; ptr && (i < rli->tables_to_lock_count);
9943 298685 ptr = ptr->next_global, i++) {
9944 /*
9945 Please see comment in above 'for' loop to know the reason
9946 for this if condition
9947 */
9948
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 298611 times.
298611 if (ptr->parent_l) continue;
9949
1/2
✓ Branch 0 taken 298685 times.
✗ Branch 1 not taken.
298611 const_cast<Relay_log_info *>(rli)->m_table_map.set_table(ptr->table_id,
9950 ptr->table);
9951 }
9952
9953 /*
9954 Validate applied binlog events with plugin requirements.
9955 */
9956 297710 int out_value = 0;
9957 int hook_error =
9958
4/6
✓ Branch 0 taken 297452 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 186491 times.
✓ Branch 3 taken 110961 times.
✓ Branch 4 taken 111015 times.
✗ Branch 5 not taken.
297710 RUN_HOOK(binlog_relay_io, applier_log_event, (thd, out_value));
9959
3/4
✓ Branch 0 taken 297516 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 297477 times.
297506 if (hook_error || out_value) {
9960 char buf[256];
9961 29 uint applier_error = ER_APPLIER_LOG_EVENT_VALIDATION_ERROR;
9962
9963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (hook_error) {
9964 applier_error = ER_RUN_HOOK_ERROR;
9965 strcpy(buf, "applier_log_event");
9966 } else {
9967
4/8
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
29 if (!thd->owned_gtid_is_empty() && thd->owned_gtid.sidno > 0) {
9968
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 thd->owned_gtid.to_string(thd->owned_sid, buf);
9969 } else {
9970 strcpy(buf, "ANONYMOUS");
9971 }
9972 }
9973
9974
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (thd->slave_thread) {
9975
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 rli->report(ERROR_LEVEL, applier_error,
9976
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ER_THD_NONCONST(thd, applier_error), buf);
9977 3 thd->is_slave_error = true;
9978
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
9979 } else {
9980 /*
9981 For the cases in which a 'BINLOG' statement is set to
9982 execute in a user session
9983 */
9984
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 my_printf_error(applier_error, ER_THD_NONCONST(thd, applier_error),
9985 MYF(0), buf);
9986 }
9987 6 return applier_error;
9988 }
9989 }
9990
9991 349651 table = m_table =
9992
1/2
✓ Branch 0 taken 349651 times.
✗ Branch 1 not taken.
349719 const_cast<Relay_log_info *>(rli)->m_table_map.get_table(m_table_id);
9993
9994
3/8
✓ Branch 0 taken 349636 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 349491 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 349491 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
349651 DBUG_PRINT("debug",
9995 ("m_table: %p, m_table_id: %llu", m_table, m_table_id.id()));
9996
9997 /*
9998 A row event comprising of a P_S table
9999 - should not be replicated (i.e executed) by the slave SQL thread.
10000 - should not be executed by the client in the form BINLOG '...' stmts.
10001 */
10002
3/4
✓ Branch 0 taken 349455 times.
✓ Branch 1 taken 123 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 349455 times.
349578 if (table && table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
10003 table = nullptr;
10004
10005
2/2
✓ Branch 0 taken 349514 times.
✓ Branch 1 taken 64 times.
349578 if (table) {
10006
2/4
✓ Branch 0 taken 349564 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 349577 times.
✗ Branch 3 not taken.
349514 this->m_fields.set_thd(thd).set_table(table);
10007
10008 /*
10009 Translate received replicated column bitmaps into local table column
10010 bitmaps. This is needed when the table has columns that are to be excluded
10011 from replication - hidden generated columns, for instance.
10012 */
10013
1/2
✓ Branch 0 taken 349592 times.
✗ Branch 1 not taken.
349577 this->m_fields.translate_bitmap(this->m_cols, this->m_local_cols);
10014
2/2
✓ Branch 0 taken 26004 times.
✓ Branch 1 taken 323588 times.
349592 if (this->m_cols.bitmap != this->m_cols_ai.bitmap)
10015
1/2
✓ Branch 0 taken 26004 times.
✗ Branch 1 not taken.
26004 this->m_fields.translate_bitmap(this->m_cols_ai, this->m_local_cols_ai);
10016 else
10017 323588 this->m_local_cols_ai.bitmap = this->m_local_cols.bitmap;
10018
10019 /*
10020 table == NULL means that this table should not be replicated
10021 (this was set up by Table_map_log_event::do_apply_event()
10022 which tested replicate-* rules).
10023 */
10024
10025
1/2
✓ Branch 0 taken 349490 times.
✗ Branch 1 not taken.
349592 Applier_security_context_guard security_context{rli, thd};
10026 349490 const char *privilege_missing = nullptr;
10027
3/4
✓ Branch 0 taken 349498 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 129 times.
✓ Branch 3 taken 349369 times.
349490 if (!security_context.skip_priv_checks()) {
10028 129 std::vector<std::tuple<ulong, const TABLE *, Rows_log_event *>> l;
10029
4/6
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
129 switch (get_general_type_code()) {
10030 69 case binary_log::WRITE_ROWS_EVENT: {
10031
2/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
69 l.push_back(std::make_tuple(INSERT_ACL, this->m_table, this));
10032
3/4
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 53 times.
69 if (!security_context.has_access(l)) {
10033 16 privilege_missing = "INSERT";
10034 }
10035 69 break;
10036 }
10037 18 case binary_log::DELETE_ROWS_EVENT: {
10038
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 l.push_back(std::make_tuple(DELETE_ACL, this->m_table, this));
10039
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
18 if (!security_context.has_access(l)) {
10040 9 privilege_missing = "DELETE";
10041 }
10042 18 break;
10043 }
10044 42 case binary_log::UPDATE_ROWS_EVENT:
10045 case binary_log::PARTIAL_UPDATE_ROWS_EVENT: {
10046
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 l.push_back(std::make_tuple(UPDATE_ACL, this->m_table, this));
10047
3/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 21 times.
42 if (!security_context.has_access(l)) {
10048 21 privilege_missing = "UPDATE";
10049 }
10050 42 break;
10051 }
10052 default: {
10053 assert(false);
10054 }
10055 }
10056 129 }
10057
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 349452 times.
349498 if (privilege_missing != nullptr) {
10058
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
138 rli->report(ERROR_LEVEL, ER_TABLEACCESS_DENIED_ERROR,
10059
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 ER_THD(thd, ER_TABLEACCESS_DENIED_ERROR), privilege_missing,
10060
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
92 security_context.get_username().data(),
10061 46 security_context.get_hostname().data(),
10062
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 table->s->table_name.str);
10063 46 return ER_TABLEACCESS_DENIED_ERROR;
10064 }
10065
10066 349452 bool no_columns_to_update = false;
10067 // set the database
10068 LEX_CSTRING thd_db;
10069 349452 LEX_CSTRING current_db_name_saved = thd->db();
10070 349307 thd_db.str = table->s->db.str;
10071 349307 thd_db.length = table->s->db.length;
10072
1/2
✓ Branch 0 taken 349545 times.
✗ Branch 1 not taken.
349307 thd->reset_db(thd_db);
10073
1/2
✓ Branch 0 taken 349487 times.
✗ Branch 1 not taken.
349545 thd->set_command(COM_QUERY);
10074 349487 PSI_stage_info *stage = nullptr;
10075
10076 /*
10077 It's not needed to set_time() but
10078 1) it continues the property that "Time" in SHOW PROCESSLIST shows how
10079 much slave is behind
10080 2) it will be needed when we allow replication from a table with no
10081 TIMESTAMP column to a table with one.
10082 So we call set_time(), like in SBR. Presently it changes nothing.
10083 */
10084
1/2
✓ Branch 0 taken 349486 times.
✗ Branch 1 not taken.
349487 thd->set_time(&(common_header->when));
10085
10086 /*
10087 We don't consider index extensions in RBR, as doing so would cause
10088 replication failure with UPDATE/DELETE when replica server has a PK on
10089 extra columns and source does not.
10090 */
10091 699027 Disable_index_extensions_switch_guard guard(thd);
10092
10093 349441 thd->binlog_row_event_extra_data = m_extra_row_info.get_ndb_info();
10094
10095 /*
10096 Now we are in a statement and will stay in a statement until we
10097 see a STMT_END_F.
10098
10099 We set this flag here, before actually applying any rows, in
10100 case the SQL thread is stopped and we need to detect that we're
10101 inside a statement and halting abruptly might cause problems
10102 when restarting.
10103 */
10104 349468 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
10105
10106
7/8
✓ Branch 0 taken 348559 times.
✓ Branch 1 taken 941 times.
✓ Branch 2 taken 348479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 345144 times.
✓ Branch 5 taken 3335 times.
✓ Branch 6 taken 345147 times.
✓ Branch 7 taken 4273 times.
349481 if (m_width == this->m_fields.filtered_size() && bitmap_is_set_all(&m_cols))
10107 345147 set_flags(COMPLETE_ROWS_F);
10108
10109 /*
10110 Set tables write and read sets.
10111
10112 Read_set contains all slave columns (in case we are going to fetch
10113 a complete record from slave)
10114
10115 Write_set equals the m_cols bitmap sent from master but it can be
10116 longer if slave has extra columns.
10117 */
10118
10119 349297 bitmap_set_all(table->read_set);
10120 349318 bitmap_set_all(table->write_set);
10121
10122 /*
10123 Call mark_generated_columns() to set read_set/write_set bits of the
10124 virtual generated columns as required in order to get these computed.
10125 This is needed since all columns need to have a value in the before
10126 image for the record when doing the update (some storage engines will
10127 use this for maintaining of secondary indexes). This call is required
10128 even for DELETE events to set write_set bit in order to satisfy
10129 ASSERTs in Field_*::store functions.
10130
10131 binlog_prepare_row_image() function, which will be called from
10132 binlogging functions (binlog_update_row() and binlog_delete_row())
10133 will take care of removing these spurious fields required during
10134 execution but not needed for binlogging. In case of inserts, there
10135 are no spurious fields (all generated columns are required to be written
10136 into the binlog).
10137 */
10138
4/6
✓ Branch 0 taken 349281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12727 times.
✓ Branch 3 taken 25983 times.
✓ Branch 4 taken 310571 times.
✗ Branch 5 not taken.
349483 switch (get_general_type_code()) {
10139 12727 case binary_log::DELETE_ROWS_EVENT:
10140
1/2
✓ Branch 0 taken 12727 times.
✗ Branch 1 not taken.
12727 bitmap_intersect(table->read_set, &this->m_local_cols);
10141 12727 stage = &stage_rpl_apply_row_evt_delete;
10142
3/4
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 12650 times.
✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
12727 if (m_table->vfield) m_table->mark_generated_columns(false);
10143 12727 break;
10144 25983 case binary_log::UPDATE_ROWS_EVENT:
10145
1/2
✓ Branch 0 taken 25983 times.
✗ Branch 1 not taken.
25983 bitmap_intersect(table->read_set, &this->m_local_cols);
10146
1/2
✓ Branch 0 taken 25983 times.
✗ Branch 1 not taken.
25983 bitmap_intersect(table->write_set, &this->m_local_cols_ai);
10147
3/4
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 25776 times.
✓ Branch 2 taken 207 times.
✗ Branch 3 not taken.
25983 if (m_table->vfield) m_table->mark_generated_columns(true);
10148 /* Skip update rows events that don't have data for this server's table.
10149 */
10150
3/4
✓ Branch 0 taken 25983 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 25939 times.
25983 if (!is_any_column_signaled_for_table(table, &this->m_local_cols_ai))
10151 44 no_columns_to_update = true;
10152 25983 stage = &stage_rpl_apply_row_evt_update;
10153 25983 break;
10154 310571 case binary_log::WRITE_ROWS_EVENT:
10155 /*
10156 For 'WRITE_ROWS_EVENT, the execution order for 'mark_generated_rows()'
10157 and bitset intersection between 'write_set' and 'm_cols', is inverted.
10158 This behaviour is necessary due to an inconsistency, between storage
10159 engines, regarding the 'm_cols' bitset and generated columns: while
10160 non-NDB engines always include the generated columns for write-rows
10161 events, NDB doesn't if not necessary. The previous execution order
10162 would set all generated columns bits to '1' in 'write_set', since
10163 'mark_generated_columns()' is expecting that every column is present
10164 in the log event. This would break replication of generated columns
10165 for NDB.
10166
10167 For engines that include every column in write-rows events, this order
10168 makes no difference, assuming that the master uses the same engine,
10169 since the master will include all the bits in the image.
10170
10171 For use-cases that use different storage engines, specifically NDB
10172 and some other, this order may break replication due to the
10173 differences in behaviour regarding generated columns bits, in
10174 wrote-rows event bitsets. This issue should be further addressed by
10175 storage engines handlers, by converging behaviour regarding such use
10176 cases.
10177 */
10178 /* WRITE ROWS EVENTS store the bitmap in the m_cols bitmap */
10179
3/4
✓ Branch 0 taken 3643 times.
✓ Branch 1 taken 306928 times.
✓ Branch 2 taken 3643 times.
✗ Branch 3 not taken.
310571 if (m_table->vfield) m_table->mark_generated_columns(false);
10180
1/2
✓ Branch 0 taken 310765 times.
✗ Branch 1 not taken.
310571 bitmap_intersect(table->write_set, &this->m_local_cols);
10181 310765 stage = &stage_rpl_apply_row_evt_write;
10182 310765 break;
10183 default:
10184 assert(false);
10185 }
10186
10187
2/2
✓ Branch 0 taken 253612 times.
✓ Branch 1 taken 95863 times.
349475 if (thd->slave_thread) // set the mode for slave
10188 253612 this->rbr_exec_mode = replica_exec_mode_options;
10189 else // set the mode for user thread
10190 95863 this->rbr_exec_mode = thd->variables.rbr_exec_mode_options;
10191
10192 // Do event specific preparations
10193
1/2
✓ Branch 0 taken 349342 times.
✗ Branch 1 not taken.
349475 error = do_before_row_operations(rli);
10194
10195 /*
10196 Bug#56662 Assertion failed: next_insert_id == 0, file handler.cc
10197 Don't allow generation of auto_increment value when processing
10198 rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'. The exception
10199 to this rule happens when the auto_inc column exists on some
10200 extra columns on the slave. In that case, do not force
10201 MODE_NO_AUTO_VALUE_ON_ZERO.
10202 */
10203 349342 sql_mode_t saved_sql_mode = thd->variables.sql_mode;
10204
3/4
✓ Branch 0 taken 349449 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 349269 times.
✓ Branch 3 taken 180 times.
349342 if (!is_auto_inc_in_extra_columns())
10205 349269 thd->variables.sql_mode |= MODE_NO_AUTO_VALUE_ON_ZERO;
10206
10207 // row processing loop
10208
10209 /*
10210 set the initial time of this ROWS statement if it was not done
10211 before in some other ROWS event.
10212 */
10213 349449 const_cast<Relay_log_info *>(rli)->set_row_stmt_start_timestamp();
10214
10215 349362 const uchar *saved_m_curr_row = m_curr_row;
10216
10217 349362 int (Rows_log_event::*do_apply_row_ptr)(Relay_log_info const *) = nullptr;
10218
10219 /**
10220 Skip update rows events that don't have data for this slave's
10221 table.
10222 */
10223
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 349318 times.
349362 if (no_columns_to_update) goto AFTER_MAIN_EXEC_ROW_LOOP;
10224
10225 /**
10226 If there are no columns marked in the read_set for this table,
10227 that means that we cannot lookup any row using the available BI
10228 in the binary log. Thence, we immediately raise an error:
10229 HA_ERR_END_OF_FILE.
10230 */
10231
10232
4/4
✓ Branch 0 taken 38666 times.
✓ Branch 1 taken 310652 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 349315 times.
387984 if ((m_rows_lookup_algorithm != ROW_LOOKUP_NOT_NEEDED) &&
10233
3/4
✓ Branch 0 taken 38666 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 38663 times.
38666 !is_any_column_signaled_for_table(table, &this->m_local_cols)) {
10234 3 error = HA_ERR_END_OF_FILE;
10235 3 goto AFTER_MAIN_EXEC_ROW_LOOP;
10236 }
10237
5/5
✓ Branch 0 taken 12314 times.
✓ Branch 1 taken 25671 times.
✓ Branch 2 taken 678 times.
✓ Branch 3 taken 310580 times.
✓ Branch 4 taken 72 times.
349315 switch (m_rows_lookup_algorithm) {
10238 12314 case ROW_LOOKUP_HASH_SCAN:
10239 12314 do_apply_row_ptr = &Rows_log_event::do_hash_scan_and_update;
10240 12314 break;
10241
10242 25671 case ROW_LOOKUP_INDEX_SCAN:
10243 25671 do_apply_row_ptr = &Rows_log_event::do_index_scan_and_update;
10244 25671 break;
10245
10246 678 case ROW_LOOKUP_TABLE_SCAN:
10247 678 do_apply_row_ptr = &Rows_log_event::do_table_scan_and_update;
10248 678 break;
10249
10250 310580 case ROW_LOOKUP_NOT_NEEDED:
10251
2/12
✓ Branch 0 taken 310623 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 310623 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
310580 assert(get_general_type_code() == binary_log::WRITE_ROWS_EVENT ||
10252 get_general_type_code() == binary_log::DELETE_ROWS_EVENT ||
10253 get_general_type_code() == binary_log::UPDATE_ROWS_EVENT);
10254
10255 /* No need to scan for rows, just apply it */
10256 310623 do_apply_row_ptr = &Rows_log_event::do_apply_row;
10257 310623 break;
10258
10259 72 default:
10260 72 assert(0);
10261 error = 1;
10262 goto AFTER_MAIN_EXEC_ROW_LOOP;
10263 break;
10264 }
10265
10266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 349286 times.
349286 assert(stage != nullptr);
10267
1/2
✓ Branch 0 taken 349433 times.
✗ Branch 1 not taken.
349286 THD_STAGE_INFO(thd, *stage);
10268
10269 #ifdef HAVE_PSI_STAGE_INTERFACE
10270
1/2
✓ Branch 0 taken 349477 times.
✗ Branch 1 not taken.
349433 m_psi_progress.set_progress(mysql_set_stage(stage->m_key));
10271 #endif
10272
10273 do {
10274
3/8
✓ Branch 0 taken 3452717 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3452709 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3452709 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3452710 DBUG_PRINT("info", ("calling do_apply_row_ptr"));
10275
10276
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3452715 times.
✓ Branch 2 taken 3452694 times.
✗ Branch 3 not taken.
3452715 error = (this->*do_apply_row_ptr)(rli);
10277
10278
2/2
✓ Branch 0 taken 3452344 times.
✓ Branch 1 taken 350 times.
3452694 if (!error) thd->updated_row_count++;
10279
10280
3/4
✓ Branch 0 taken 3452671 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 325 times.
✓ Branch 3 taken 3452346 times.
3452694 if (handle_idempotent_and_ignored_errors(rli, &error)) break;
10281
10282 /* this advances m_curr_row */
10283
1/2
✓ Branch 0 taken 3452434 times.
✗ Branch 1 not taken.
3452346 do_post_row_operations(rli, error);
10284
10285
4/4
✓ Branch 0 taken 3452433 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3103282 times.
✓ Branch 3 taken 349151 times.
3452434 } while (!error && (m_curr_row != m_rows_end));
10286
10287
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 349447 times.
349477 if (unlikely(opt_userstat)) {
10288 7 thd->update_stats(false);
10289
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 update_global_user_stats(thd, true, my_getsystime());
10290 }
10291
10292 #ifdef HAVE_PSI_STAGE_INTERFACE
10293 349454 m_psi_progress.end_work();
10294 #endif
10295
10296 349496 AFTER_MAIN_EXEC_ROW_LOOP:
10297
10298
6/6
✓ Branch 0 taken 349251 times.
✓ Branch 1 taken 245 times.
✓ Branch 2 taken 36522 times.
✓ Branch 3 taken 312709 times.
✓ Branch 4 taken 36524 times.
✓ Branch 5 taken 312952 times.
349496 if (saved_m_curr_row != m_curr_row && !table->file->has_transactions()) {
10299 /*
10300 Usually, the trans_commit_stmt() propagates unsafe_rollback_flags
10301 from statement to transaction level. However, we cannot rely on
10302 this when row format is in use as several events can be processed
10303 before calling this function. This happens because it is called
10304 only when the latest event generated by a statement is processed.
10305
10306 There are however upper level functions that execute per event
10307 and check transaction's status. So if the unsafe_rollback_flags
10308 are not propagated here, this can lead to errors.
10309
10310 For example, a transaction that updates non-transactional tables
10311 may be stopped in the middle thus leading to inconsistencies
10312 after a restart.
10313 */
10314
1/2
✓ Branch 0 taken 36558 times.
✗ Branch 1 not taken.
36524 thd->get_transaction()->mark_modified_non_trans_table(
10315 Transaction_ctx::STMT);
10316
1/2
✓ Branch 0 taken 36560 times.
✗ Branch 1 not taken.
36558 thd->get_transaction()->merge_unsafe_rollback_flags();
10317 }
10318
10319 /*
10320 Restore the sql_mode after the rows event is processed.
10321 */
10322 349512 thd->variables.sql_mode = saved_sql_mode;
10323
10324 {
10325 /*
10326 The following failure injecion works in cooperation with tests
10327 setting @@global.debug= 'd,stop_replica_middle_group'.
10328 The sql thread receives the killed status and will proceed
10329 to shutdown trying to finish incomplete events group.
10330 */
10331
2/8
✓ Branch 0 taken 349509 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 349509 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
349512 DBUG_EXECUTE_IF("stop_replica_middle_group", {
10332 if (thd->get_transaction()->cannot_safely_rollback(
10333 Transaction_ctx::SESSION)) {
10334 auto thd_rli = (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL
10335 ? const_cast<Relay_log_info *>(rli)
10336 : static_cast<Slave_worker *>(
10337 const_cast<Relay_log_info *>(rli))
10338 ->c_rli);
10339 thd_rli->abort_slave = 1;
10340 }
10341 };);
10342 }
10343
10344
4/6
✓ Branch 0 taken 349527 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 286 times.
✓ Branch 3 taken 349241 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 349528 times.
349796 if ((error = do_after_row_operations(rli, error)) &&
10345
3/6
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 287 times.
286 ignored_error_code(convert_handler_error(error, thd, table))) {
10346 slave_rows_error_report(
10347 INFORMATION_LEVEL, error, rli, thd, table, get_type_str(),
10348 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10349 (ulong)common_header->log_pos);
10350 thd->get_stmt_da()->reset_condition_info(thd);
10351 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
10352 error = 0;
10353 }
10354
10355 // reset back the db
10356
1/2
✓ Branch 0 taken 349541 times.
✗ Branch 1 not taken.
349528 thd->reset_db(current_db_name_saved);
10357
2/2
✓ Branch 0 taken 349530 times.
✓ Branch 1 taken 52 times.
349571 } // if (table)
10358
10359
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 349308 times.
349594 if (error) {
10360
2/4
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 287 times.
✗ Branch 3 not taken.
287 slave_rows_error_report(
10361 ERROR_LEVEL, error, rli, thd, table, get_type_str(),
10362 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10363 286 (ulong)common_header->log_pos);
10364 /*
10365 @todo We should probably not call
10366 reset_current_stmt_binlog_format_row() from here.
10367 /Sven
10368 */
10369
1/2
✓ Branch 0 taken 287 times.
✗ Branch 1 not taken.
287 thd->reset_current_stmt_binlog_format_row();
10370 287 thd->is_slave_error = true;
10371 287 return error;
10372 }
10373
10374 349308 end:
10375
2/2
✓ Branch 0 taken 299099 times.
✓ Branch 1 taken 52167 times.
351238 if (get_flags(STMT_END_F)) {
10376
3/4
✓ Branch 0 taken 299166 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 299161 times.
299099 if ((error = rows_event_stmt_cleanup(rli, thd))) {
10377
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (table)
10378
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
8 slave_rows_error_report(
10379
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 ERROR_LEVEL, thd->is_error() ? 0 : error, rli, thd, table,
10380 get_type_str(),
10381 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10382 4 (ulong)common_header->log_pos);
10383 else {
10384
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 rli->report(
10385 ERROR_LEVEL,
10386
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 thd->is_error() ? thd->get_stmt_da()->mysql_errno() : error,
10387 "Error in cleaning up after an event of type:%s; %s; the group"
10388 " log file/position: %s %lu",
10389 get_type_str(),
10390
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 thd->is_error() ? thd->get_stmt_da()->message_text()
10391 : "unexpected error",
10392 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10393 1 (ulong)common_header->log_pos);
10394 }
10395 }
10396 /* We are at end of the statement (STMT_END_F flag), lets clean
10397 the memory which was used from thd's mem_root now.
10398 This needs to be done only if we are here in SQL thread context.
10399 In other flow ( in case of a regular thread which can happen
10400 when the thread is applying BINLOG'...' row event) we should
10401 *not* try to free the memory here. It will be done latter
10402 in dispatch_command() after command execution is completed.
10403 */
10404 #ifdef WITH_WSREP
10405
5/6
✓ Branch 0 taken 248622 times.
✓ Branch 1 taken 50544 times.
✓ Branch 2 taken 245909 times.
✓ Branch 3 taken 2713 times.
✓ Branch 4 taken 296413 times.
✗ Branch 5 not taken.
299166 if (thd->wsrep_applier || thd->slave_thread) thd->mem_root->ClearForReuse();
10406 #else
10407 if (thd->slave_thread) thd->mem_root->ClearForReuse();
10408 #endif
10409 }
10410 351293 return error;
10411 351902 }
10412
10413 256124 Log_event::enum_skip_reason Rows_log_event::do_shall_skip(Relay_log_info *rli) {
10414 /*
10415 If the slave skip counter is 1 and this event does not end a
10416 statement, then we should not start executing on the next event.
10417 Otherwise, we defer the decision to the normal skipping logic.
10418 */
10419
6/6
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 255877 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 242 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 256119 times.
256124 if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F))
10420 5 return Log_event::EVENT_SKIP_IGNORE;
10421 else
10422 256119 return Log_event::do_shall_skip(rli);
10423 }
10424
10425 /**
10426 The function is called at Rows_log_event statement commit time,
10427 normally from Rows_log_event::do_update_pos() and possibly from
10428 Query_log_event::do_apply_event() of the COMMIT.
10429 The function commits the last statement for engines, binlog and
10430 releases resources have been allocated for the statement.
10431
10432 @retval 0 Ok.
10433 @retval non-zero Error at the commit.
10434 */
10435
10436 299048 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD *thd) {
10437
1/2
✓ Branch 0 taken 299155 times.
✗ Branch 1 not taken.
299048 DBUG_TRACE;
10438
5/8
✓ Branch 0 taken 299142 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 299141 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
299155 DBUG_EXECUTE_IF("simulate_rows_event_cleanup_failure", {
10439 char errbuf[MYSQL_ERRMSG_SIZE];
10440 int err = 149;
10441 my_error(ER_ERROR_DURING_COMMIT, MYF(0), err,
10442 my_strerror(errbuf, MYSQL_ERRMSG_SIZE, err));
10443 return 1;
10444 });
10445 int error;
10446 {
10447 /*
10448 This is the end of a statement or transaction, so close (and
10449 unlock) the tables we opened when processing the
10450 Table_map_log_event starting the statement.
10451
10452 OBSERVER. This will clear *all* mappings, not only those that
10453 are open for the table. There is not good handle for on-close
10454 actions for tables.
10455
10456 NOTE. Even if we have no table ('table' == 0) we still need to be
10457 here, so that we increase the group relay log position. If we didn't, we
10458 could have a group relay log position which lags behind "forever"
10459 (assume the last master's transaction is ignored by the slave because of
10460 replicate-ignore rules).
10461 */
10462
1/2
✓ Branch 0 taken 299151 times.
✗ Branch 1 not taken.
299141 error = thd->binlog_flush_pending_rows_event(true);
10463
10464 /*
10465 If this event is not in a transaction, the call below will, if some
10466 transactional storage engines are involved, commit the statement into
10467 them and flush the pending event to binlog.
10468 If this event is in a transaction, the call will do nothing, but a
10469 Xid_log_event will come next which will, if some transactional engines
10470 are involved, commit the transaction and flush the pending event to the
10471 binlog.
10472 If there was a deadlock the transaction should have been rolled back
10473 already. So there should be no need to rollback the transaction.
10474 */
10475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 299151 times.
299151 assert(!thd->transaction_rollback_request);
10476
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 299151 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
299151 error |= ((error != 0) ? static_cast<int>(trans_rollback_stmt(thd))
10477
1/2
✓ Branch 0 taken 299131 times.
✗ Branch 1 not taken.
299151 : static_cast<int>(trans_commit_stmt(thd)));
10478
10479 /*
10480 Now what if this is not a transactional engine? we still need to
10481 flush the pending event to the binlog; we did it with
10482 thd->binlog_flush_pending_rows_event(). Note that we imitate
10483 what is done for real queries: a call to
10484 ha_autocommit_or_rollback() (sometimes only if involves a
10485 transactional engine), and a call to be sure to have the pending
10486 event flushed.
10487 */
10488
10489 /*
10490 @todo We should probably not call
10491 reset_current_stmt_binlog_format_row() from here.
10492
10493 Btw, the previous comment about transactional engines does not
10494 seem related to anything that happens here.
10495 /Sven
10496 */
10497
1/2
✓ Branch 0 taken 299171 times.
✗ Branch 1 not taken.
299131 thd->reset_current_stmt_binlog_format_row();
10498
10499
1/2
✓ Branch 0 taken 299170 times.
✗ Branch 1 not taken.
299171 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, false);
10500
10501 /*
10502 Clean sql_command value
10503 */
10504 299170 thd->lex->sql_command = SQLCOM_END;
10505 }
10506 299170 return error;
10507 299171 }
10508
10509 /**
10510 The method either increments the relay log position or
10511 commits the current statement and increments the master group
10512 position if the event is STMT_END_F flagged and
10513 the statement corresponds to the autocommit query (i.e replicated
10514 without wrapping in BEGIN/COMMIT)
10515
10516 @retval 0 Success
10517 @retval non-zero Error in the statement commit
10518 */
10519 437 int Rows_log_event::do_update_pos(Relay_log_info *rli) {
10520
1/2
✓ Branch 0 taken 437 times.
✗ Branch 1 not taken.
437 DBUG_TRACE;
10521 437 int error = 0;
10522
10523
3/10
✓ Branch 0 taken 437 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 437 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 437 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
437 DBUG_PRINT("info", ("flags: %s", get_flags(STMT_END_F) ? "STMT_END_F " : ""));
10524
10525 /* Worker does not execute binlog update position logics */
10526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 437 times.
437 assert(!is_mts_worker(rli->info_thd));
10527
10528
2/2
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 43 times.
437 if (get_flags(STMT_END_F)) {
10529 /*
10530 Indicate that a statement is finished.
10531 Step the group log position if we are not in a transaction,
10532 otherwise increase the event log position.
10533 */
10534
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 error = rli->stmt_done(common_header->log_pos);
10535 } else {
10536 43 rli->inc_event_relay_log_pos();
10537 }
10538
10539 437 return error;
10540 437 }
10541
10542 4640161 bool Rows_log_event::write_data_header(Basic_ostream *ostream) {
10543 uchar
10544 buf[Binary_log_event::ROWS_HEADER_LEN_V2]; // No need to init the buffer
10545
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4640252 times.
4640161 assert(m_table_id.is_valid());
10546
2/6
✓ Branch 0 taken 4640236 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4640236 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4640252 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_source", {
10547 int4store(buf + 0, (ulong)m_table_id.id());
10548 int2store(buf + 4, m_flags);
10549 return (wrapper_my_b_safe_write(ostream, buf, 6));
10550 });
10551 4640236 int6store(buf + ROWS_MAPID_OFFSET, m_table_id.id());
10552 4640198 int2store(buf + ROWS_FLAGS_OFFSET, m_flags);
10553
2/2
✓ Branch 0 taken 4640195 times.
✓ Branch 1 taken 4 times.
4640240 if (likely(!log_bin_use_v1_row_events)) {
10554 /*
10555 v2 event, with variable header portion.
10556 Determine length of variable header payload(extra_row_info part)
10557 */
10558 4640195 uint extra_row_info_payloadlen = EXTRA_ROW_INFO_HEADER_LENGTH;
10559
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 4639597 times.
4640195 if (m_extra_row_info.have_ndb_info()) {
10560 623 extra_row_info_payloadlen +=
10561
1/2
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
623 (EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_ndb_length());
10562 ;
10563 }
10564
10565
2/2
✓ Branch 0 taken 414246 times.
✓ Branch 1 taken 4225983 times.
4640220 if (m_extra_row_info.have_part()) {
10566 414246 extra_row_info_payloadlen +=
10567
1/2
✓ Branch 0 taken 414246 times.
✗ Branch 1 not taken.
414246 (EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_part_length());
10568 }
10569 /* Var-size header len includes len itself */
10570 4640229 int2store(buf + ROWS_VHLEN_OFFSET, extra_row_info_payloadlen);
10571
2/4
✓ Branch 0 taken 4640338 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4640338 times.
4640256 if (wrapper_my_b_safe_write(ostream, buf,
10572 Binary_log_event::ROWS_HEADER_LEN_V2))
10573 return true;
10574
10575 /* Write var-sized payload, if any */
10576
2/2
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 4639680 times.
4640338 if (m_extra_row_info.have_ndb_info()) {
10577 /* Add tag and extra row info */
10578 623 uint8 type_code = static_cast<uint8>(enum_extra_row_info_typecode::NDB);
10579
2/4
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 623 times.
623 if (wrapper_my_b_safe_write(ostream, &(type_code),
10580 EXTRA_ROW_INFO_TYPECODE_LENGTH))
10581 return true;
10582
2/4
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 623 times.
623 if (wrapper_my_b_safe_write(ostream, m_extra_row_info.get_ndb_info(),
10583
1/2
✓ Branch 0 taken 623 times.
✗ Branch 1 not taken.
623 m_extra_row_info.get_ndb_length()))
10584 return true;
10585 }
10586
2/2
✓ Branch 0 taken 414287 times.
✓ Branch 1 taken 4225893 times.
4640303 if (m_extra_row_info.have_part()) {
10587 uint8 type_code;
10588 414287 type_code = static_cast<uint8>(enum_extra_row_info_typecode::PART);
10589 uchar partition_buf[5];
10590 414287 uint8 extra_part_info_data_len = 0;
10591 414287 partition_buf[extra_part_info_data_len++] = type_code;
10592
10593 // partition_id occupies less than 2 bytes
10594 // in all the cases because of the current range of allowed number
10595 // of partitions 8192 for non-ndb and 12288 for ndb.
10596 // So while writing the partition_id it is okay to use 2 bytes for it.
10597
10598 414287 int write_partition_id = m_extra_row_info.get_partition_id();
10599 414246 int2store(partition_buf + extra_part_info_data_len,
10600 static_cast<uint16>(write_partition_id));
10601 414246 extra_part_info_data_len += EXTRA_ROW_PART_INFO_VALUE_LENGTH;
10602
10603
3/4
✓ Branch 0 taken 414246 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76652 times.
✓ Branch 3 taken 337594 times.
414246 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
10604 76652 write_partition_id = m_extra_row_info.get_source_partition_id();
10605 76652 int2store(partition_buf + extra_part_info_data_len,
10606 static_cast<uint16>(write_partition_id));
10607 76652 extra_part_info_data_len += EXTRA_ROW_PART_INFO_VALUE_LENGTH;
10608 }
10609
10610
2/4
✓ Branch 0 taken 414246 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 414246 times.
414246 if (wrapper_my_b_safe_write(ostream, partition_buf,
10611 extra_part_info_data_len))
10612 return true;
10613 }
10614 } else {
10615
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (wrapper_my_b_safe_write(ostream, buf,
10616 Binary_log_event::ROWS_HEADER_LEN_V1))
10617 return true;
10618 }
10619
10620 4640143 return false;
10621 }
10622
10623 4640155 bool Rows_log_event::write_data_body(Basic_ostream *ostream) {
10624 /*
10625 Note that this should be the number of *bits*, not the number of
10626 bytes.
10627 */
10628 uchar sbuf[sizeof(m_width) + 1];
10629 4640155 ptrdiff_t const data_size = m_rows_cur - m_rows_buf;
10630 4640155 bool res = false;
10631
1/2
✓ Branch 0 taken 4640237 times.
✗ Branch 1 not taken.
4640155 uchar *const sbuf_end = net_store_length(sbuf, (size_t)m_width);
10632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4640237 times.
4640237 assert(static_cast<size_t>(sbuf_end - sbuf) <= sizeof(sbuf));
10633
10634
1/2
✓ Branch 0 taken 4640250 times.
✗ Branch 1 not taken.
4640237 DBUG_DUMP("m_width", sbuf, (size_t)(sbuf_end - sbuf));
10635 4640352 res =
10636
3/6
✓ Branch 0 taken 4640250 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4640352 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4640352 times.
4640250 res || wrapper_my_b_safe_write(ostream, sbuf, (size_t)(sbuf_end - sbuf));
10637
10638
1/2
✓ Branch 0 taken 4640333 times.
✗ Branch 1 not taken.
4640352 DBUG_DUMP("m_cols", (uchar *)m_cols.bitmap, no_bytes_in_map(&m_cols));
10639
3/4
✓ Branch 0 taken 4640320 times.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4640338 times.
9280671 res = res || wrapper_my_b_safe_write(ostream, (uchar *)m_cols.bitmap,
10640
1/2
✓ Branch 0 taken 4640338 times.
✗ Branch 1 not taken.
4640320 no_bytes_in_map(&m_cols));
10641 /*
10642 TODO[refactor write]: Remove the "down cast" here (and elsewhere).
10643 */
10644
3/4
✓ Branch 0 taken 4640338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 227884 times.
✓ Branch 3 taken 4412454 times.
4640351 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
10645
1/2
✓ Branch 0 taken 227884 times.
✗ Branch 1 not taken.
227884 DBUG_DUMP("m_cols_ai", (uchar *)m_cols_ai.bitmap,
10646 no_bytes_in_map(&m_cols_ai));
10647
2/4
✓ Branch 0 taken 227884 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 227884 times.
455768 res = res || wrapper_my_b_safe_write(ostream, (uchar *)m_cols_ai.bitmap,
10648
1/2
✓ Branch 0 taken 227884 times.
✗ Branch 1 not taken.
227884 no_bytes_in_map(&m_cols_ai));
10649 }
10650
1/2
✓ Branch 0 taken 4640266 times.
✗ Branch 1 not taken.
4640338 DBUG_DUMP("rows", m_rows_buf, data_size);
10651
4/6
✓ Branch 0 taken 4640272 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4640332 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 4640309 times.
4640266 res = res || wrapper_my_b_safe_write(ostream, m_rows_buf, (size_t)data_size);
10652
10653 4640326 return res;
10654 }
10655
10656 35469 int Rows_log_event::pack_info(Protocol *protocol) {
10657 char buf[256];
10658
2/2
✓ Branch 0 taken 32458 times.
✓ Branch 1 taken 3011 times.
35469 char const *const flagstr = get_flags(STMT_END_F) ? " flags: STMT_END_F" : "";
10659 size_t bytes =
10660 35469 snprintf(buf, sizeof(buf), "table_id: %llu%s", m_table_id.id(), flagstr);
10661
1/2
✓ Branch 0 taken 35469 times.
✗ Branch 1 not taken.
35469 protocol->store_string(buf, bytes, &my_charset_bin);
10662 35469 return 0;
10663 }
10664 #endif // MYSQL_SERVER
10665
10666 #ifndef MYSQL_SERVER
10667 36213 void Rows_log_event::print_helper(FILE *,
10668 PRINT_EVENT_INFO *print_event_info) const {
10669 36213 IO_CACHE *const head = &print_event_info->head_cache;
10670 36213 IO_CACHE *const body = &print_event_info->body_cache;
10671
2/2
✓ Branch 0 taken 36211 times.
✓ Branch 1 taken 2 times.
36213 if (!print_event_info->short_form) {
10672 36211 bool const last_stmt_event = get_flags(STMT_END_F);
10673 36211 print_header(head, print_event_info, !last_stmt_event);
10674
2/2
✓ Branch 0 taken 35943 times.
✓ Branch 1 taken 268 times.
72422 my_b_printf(head, "\t%s: table id %llu%s\n", get_type_str(),
10675 36211 m_table_id.id(), last_stmt_event ? " flags: STMT_END_F" : "");
10676 36211 print_base64(body, print_event_info, !last_stmt_event);
10677 }
10678 36213 }
10679 #endif
10680
10681 /**************************************************************************
10682 Table_map_log_event member functions and support functions
10683 **************************************************************************/
10684
10685 /**
10686 @ingroup Replication
10687
10688 @page PAGE_RPL_FIELD_METADATA How replication of field metadata works.
10689
10690 When a table map is created, the master first calls
10691 Table_map_log_event::save_field_metadata() which calculates how many
10692 values will be in the field metadata. Only those fields that require the
10693 extra data are added. The method also loops through all of the fields in
10694 the table calling the method Field::save_field_metadata() which returns the
10695 values for the field that will be saved in the metadata and replicated to
10696 the slave. Once all fields have been processed, the table map is written to
10697 the binlog adding the size of the field metadata and the field metadata to
10698 the end of the body of the table map.
10699
10700 When a table map is read on the slave, the field metadata is read from the
10701 table map and passed to the table_def class constructor which saves the
10702 field metadata from the table map into an array based on the type of the
10703 field. Field metadata values not present (those fields that do not use extra
10704 data) in the table map are initialized as zero (0). The array size is the
10705 same as the columns for the table on the slave.
10706
10707 Additionally, values saved for field metadata on the master are saved as a
10708 string of bytes (uchar) in the binlog. A field may require 1 or more bytes
10709 to store the information. In cases where values require multiple bytes
10710 (e.g. values > 255), the endian-safe methods are used to properly encode
10711 the values on the master and decode them on the slave. When the field
10712 metadata values are captured on the slave, they are stored in an array of
10713 type uint. This allows the least number of casts to prevent casting bugs
10714 when the field metadata is used in comparisons of field attributes. When
10715 the field metadata is used for calculating addresses in pointer math, the
10716 type used is uint32.
10717 */
10718
10719 #if defined(MYSQL_SERVER)
10720 /**
10721 Save the field metadata based on the real_type of the field.
10722 The metadata saved depends on the type of the field. Some fields
10723 store a single byte for pack_length() while others store two bytes
10724 for field_length (max length).
10725
10726 @retval 0 Ok.
10727
10728 @todo
10729 We may want to consider changing the encoding of the information.
10730 Currently, the code attempts to minimize the number of bytes written to
10731 the tablemap. There are at least two other alternatives; 1) using
10732 net_store_length() to store the data allowing it to choose the number of
10733 bytes that are appropriate thereby making the code much easier to
10734 maintain (only 1 place to change the encoding), or 2) use a fixed number
10735 of bytes for each field. The problem with option 1 is that net_store_length()
10736 will use one byte if the value < 251, but 3 bytes if it is > 250. Thus,
10737 for fields like CHAR which can be no larger than 255 characters, the method
10738 will use 3 bytes when the value is > 250. Further, every value that is
10739 encoded using 2 parts (e.g., pack_length, field_length) will be numerically
10740 > 250 therefore will use 3 bytes for eah value. The problem with option 2
10741 is less wasteful for space but does waste 1 byte for every field that does
10742 not encode 2 parts.
10743 */
10744 4247102 int Table_map_log_event::save_field_metadata() {
10745
1/2
✓ Branch 0 taken 4247149 times.
✗ Branch 1 not taken.
4247102 DBUG_TRACE;
10746 4247149 int index = 0;
10747
6/10
✓ Branch 0 taken 4247177 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16049178 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20296314 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20296373 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16049192 times.
✓ Branch 9 taken 4247150 times.
20296323 for (auto it = this->m_fields.begin(); it != this->m_fields.end(); ++it) {
10748
1/2
✓ Branch 0 taken 16049197 times.
✗ Branch 1 not taken.
16049192 Field *field = *it;
10749
5/8
✓ Branch 0 taken 16049088 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16049083 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 398 times.
✓ Branch 5 taken 16048685 times.
✓ Branch 6 taken 398 times.
✗ Branch 7 not taken.
16049197 DBUG_PRINT("debug", ("field_type: %d", m_coltype[it.filtered_pos()]));
10750
1/2
✓ Branch 0 taken 16049122 times.
✗ Branch 1 not taken.
16049083 index += field->save_field_metadata(&m_field_metadata[index]);
10751
10752
5/6
✓ Branch 0 taken 16049174 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 16049172 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
16049122 DBUG_EXECUTE_IF("inject_invalid_blob_size", {
10753 if (m_coltype[it.filtered_pos()] == MYSQL_TYPE_BLOB)
10754 m_field_metadata[index - 1] = 5;
10755 });
10756 4247150 }
10757 4247150 return index;
10758 4247156 }
10759
10760 /*
10761 Constructor used to build an event for writing to the binary log.
10762 Mats says tbl->s lives longer than this event so it's ok to copy pointers
10763 (tbl->s->db etc) and not pointer content.
10764 */
10765
10766 4246984 Table_map_log_event::Table_map_log_event(THD *thd_arg, TABLE *tbl,
10767 4246984 const Table_id &tid, bool using_trans)
10768 : binary_log::Table_map_event(
10769 tid,
10770 8494061 tbl->s->fields +
10771
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 4247068 times.
4247077 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event",
10772 -1, 0),
10773 12741005 (tbl->s->db.str), ((tbl->s->db.str) ? tbl->s->db.length : 0),
10774 4246984 (tbl->s->table_name.str), (tbl->s->table_name.length)),
10775 Log_event(thd_arg, 0,
10776 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
10777 : Log_event::EVENT_STMT_CACHE,
10778 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
10779
5/8
✓ Branch 0 taken 4247037 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3916671 times.
✓ Branch 3 taken 330392 times.
✓ Branch 4 taken 4247046 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4247032 times.
✗ Branch 7 not taken.
8494061 m_fields{tbl, Replicated_columns_view::OUTBOUND} {
10780 4247032 common_header->type_code = binary_log::TABLE_MAP_EVENT;
10781 4247032 m_table = tbl;
10782 4247032 m_flags = TM_BIT_LEN_EXACT_F;
10783
10784 4247077 this->m_colcnt =
10785 4247032 this->m_fields.filtered_size() +
10786
3/4
✓ Branch 0 taken 4247077 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 4247068 times.
4247033 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event", -1, 0);
10787
10788 uchar cbuf[sizeof(m_colcnt) + 1];
10789 uchar *cbuf_end;
10790
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 4247050 times.
4247077 assert(m_table_id.is_valid());
10791 /*
10792 In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in
10793 table.cc / alloc_table_share():
10794 Use the fact the key is db/0/table_name/0
10795 As we rely on this let's assert it.
10796 */
10797
2/4
✓ Branch 0 taken 4247085 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4247085 times.
4247050 assert((tbl->s->db.str == nullptr) ||
10798 (tbl->s->db.str[tbl->s->db.length] == 0));
10799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247050 times.
4247050 assert(tbl->s->table_name.str[tbl->s->table_name.length] == 0);
10800
10801 4247050 m_data_size = Binary_log_event::TABLE_MAP_HEADER_LEN;
10802
2/4
✓ Branch 0 taken 4247072 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4247072 times.
4247050 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_source", m_data_size = 6;);
10803
10804 uchar dbuf[sizeof(m_dblen) + 1];
10805 uchar tbuf[sizeof(m_tbllen) + 1];
10806
1/2
✓ Branch 0 taken 4246996 times.
✗ Branch 1 not taken.
4247072 uchar *const dbuf_end = net_store_length(dbuf, (size_t)m_dblen);
10807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4246996 times.
4246996 assert(static_cast<size_t>(dbuf_end - dbuf) <= sizeof(dbuf));
10808
1/2
✓ Branch 0 taken 4247024 times.
✗ Branch 1 not taken.
4246996 uchar *const tbuf_end = net_store_length(tbuf, (size_t)m_tbllen);
10809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247024 times.
4247024 assert(static_cast<size_t>(tbuf_end - tbuf) <= sizeof(tbuf));
10810
10811 4247024 m_data_size +=
10812 4247024 m_dblen + 1 + (dbuf_end - dbuf); // Include length and terminating \0
10813 4247024 m_data_size +=
10814 4247024 m_tbllen + 1 + (tbuf_end - tbuf); // Include length and terminating \0
10815
1/2
✓ Branch 0 taken 4247095 times.
✗ Branch 1 not taken.
4247024 cbuf_end = net_store_length(cbuf, (size_t)m_colcnt);
10816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247095 times.
4247095 assert(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
10817 4247095 m_data_size += (cbuf_end - cbuf) + m_colcnt; // COLCNT and column types
10818
10819
1/2
✓ Branch 0 taken 4247170 times.
✗ Branch 1 not taken.
4247095 m_coltype = (uchar *)my_malloc(key_memory_log_event, m_colcnt, MYF(MY_WME));
10820
10821
4/6
✓ Branch 0 taken 4247144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 4247135 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4247144 times.
4247170 assert(m_colcnt ==
10822 this->m_fields.filtered_size() +
10823 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event",
10824 -1, 0));
10825
10826
1/2
✓ Branch 0 taken 4247149 times.
✗ Branch 1 not taken.
4247144 for (auto it = this->m_fields.begin();
10827
7/12
✓ Branch 0 taken 20296344 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20296273 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16049148 times.
✓ Branch 5 taken 4247125 times.
✓ Branch 6 taken 20296315 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16049149 times.
✓ Branch 9 taken 4247174 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
36345503 it != this->m_fields.end() &&
10828
5/6
✓ Branch 0 taken 16049151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 16049133 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 6 times.
16049148 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event",
10829 it.filtered_pos() != this->m_colcnt, true);
10830 16049146 ++it) {
10831
1/2
✓ Branch 0 taken 16049158 times.
✗ Branch 1 not taken.
16049149 Field *field = *it;
10832
2/4
✓ Branch 0 taken 16049114 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16049203 times.
✗ Branch 3 not taken.
16049158 m_coltype[it.filtered_pos()] = field->binlog_type();
10833 4247174 }
10834
3/4
✓ Branch 0 taken 4247089 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4247088 times.
4247168 DBUG_EXECUTE_IF("inject_invalid_column_type", m_coltype[1] = 230;);
10835
10836 /*
10837 Calculate a bitmap for the results of maybe_null() for all columns.
10838 The bitmap is used to determine when there is a column from the master
10839 that is not on the slave and is null and thus not in the row data during
10840 replication.
10841 */
10842 4247089 uint num_null_bytes = (m_colcnt + 7) / 8;
10843 4247089 m_data_size += num_null_bytes;
10844 /*
10845 m_null_bits is a pointer indicating which columns can have a null value
10846 in a particular table.
10847 */
10848 4247143 m_null_bits =
10849
1/2
✓ Branch 0 taken 4247143 times.
✗ Branch 1 not taken.
4247089 (uchar *)my_malloc(key_memory_log_event, num_null_bytes, MYF(MY_WME));
10850
10851 4247174 m_field_metadata =
10852
1/2
✓ Branch 0 taken 4247174 times.
✗ Branch 1 not taken.
4247143 (uchar *)my_malloc(key_memory_log_event, (m_colcnt * 4), MYF(MY_WME));
10853 4247174 memset(m_field_metadata, 0, (m_colcnt * 4));
10854
10855 4247174 common_header->set_is_valid(m_null_bits != nullptr &&
10856
3/4
✓ Branch 0 taken 4247172 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4247176 times.
✗ Branch 3 not taken.
8494350 m_field_metadata != nullptr &&
10857
1/2
✓ Branch 0 taken 4247181 times.
✗ Branch 1 not taken.
4247176 m_coltype != nullptr);
10858 /*
10859 Create an array for the field metadata and store it.
10860 */
10861
1/2
✓ Branch 0 taken 4247152 times.
✗ Branch 1 not taken.
4247168 m_field_metadata_size = save_field_metadata();
10862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247152 times.
4247152 assert(m_field_metadata_size <= (m_colcnt * 4));
10863
10864 /*
10865 Now set the size of the data to the size of the field metadata array
10866 plus one or three bytes (see pack.c:net_store_length) for number of
10867 elements in the field metadata array.
10868 */
10869
2/2
✓ Branch 0 taken 4247118 times.
✓ Branch 1 taken 34 times.
4247152 if (m_field_metadata_size < 251)
10870 4247118 m_data_size += m_field_metadata_size + 1;
10871 else
10872 34 m_data_size += m_field_metadata_size + 3;
10873
10874 4247152 memset(m_null_bits, 0, num_null_bytes);
10875
1/2
✓ Branch 0 taken 4247099 times.
✗ Branch 1 not taken.
4247152 Bit_writer bit_writer{this->m_null_bits};
10876
8/14
✓ Branch 0 taken 4247177 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247167 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16049221 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16049223 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20296248 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 20296360 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 16049200 times.
✓ Branch 13 taken 4247159 times.
20296230 for (auto field : this->m_fields) bit_writer.set(field->is_nullable());
10877 /*
10878 Marking event to require sequential execution in MTS
10879 if the query might have updated FK-referenced db.
10880 Unlike Query_log_event where this fact is encoded through
10881 the accessed db list in the Table_map case m_flags is exploited.
10882 */
10883 4247153 uchar dbs = thd_arg->get_binlog_accessed_db_names()
10884 1111 ? thd_arg->get_binlog_accessed_db_names()->elements
10885
2/2
✓ Branch 0 taken 1111 times.
✓ Branch 1 taken 4245929 times.
4248151 : 0;
10886
2/2
✓ Branch 0 taken 1111 times.
✓ Branch 1 taken 4245929 times.
4247040 if (dbs == 1) {
10887 1111 char *db_name = thd_arg->get_binlog_accessed_db_names()->head();
10888
1/2
✓ Branch 0 taken 1111 times.
✗ Branch 1 not taken.
1111 if (!strcmp(db_name, "")) m_flags |= TM_REFERRED_FK_DB_F;
10889 }
10890
10891
3/4
✓ Branch 0 taken 4247039 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✓ Branch 3 taken 4246985 times.
4247040 if (table_has_generated_invisible_primary_key(m_table))
10892 54 m_flags |= TM_GENERATED_INVISIBLE_PK_F;
10893
10894
1/2
✓ Branch 0 taken 4247113 times.
✗ Branch 1 not taken.
4247039 init_metadata_fields();
10895 4247113 m_data_size += m_metadata_buf.length();
10896 4247125 }
10897 #endif /* defined(MYSQL_SERVER) */
10898
10899 /*
10900 Constructor used by slave to read the event from the binary log.
10901 */
10902 5440123 Table_map_log_event::Table_map_log_event(
10903 5440123 const char *buf, const Format_description_event *description_event)
10904 : binary_log::Table_map_event(buf, description_event),
10905 40632 Log_event(header(), footer())
10906 #ifdef MYSQL_SERVER
10907 ,
10908 5399547 m_table(nullptr),
10909
2/4
✓ Branch 0 taken 5399547 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5399502 times.
✗ Branch 3 not taken.
5399491 m_fields(Replicated_columns_view::INBOUND)
10910 #endif
10911 {
10912
1/2
✓ Branch 0 taken 5440224 times.
✗ Branch 1 not taken.
5440134 DBUG_TRACE;
10913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5440223 times.
5440224 assert(header()->type_code == binary_log::TABLE_MAP_EVENT);
10914 5440223 }
10915
10916 30254464 Table_map_log_event::~Table_map_log_event() = default;
10917
10918 /*
10919 Return value is an error code, one of:
10920
10921 -1 Failure to open table [from open_tables()]
10922 0 Success
10923 1 No room for more tables [from set_table()]
10924 2 Out of memory [from set_table()]
10925 3 Wrong table definition
10926 4 Daisy-chaining RBR with SBR not possible
10927 */
10928
10929 #if defined(MYSQL_SERVER)
10930
10931 enum enum_tbl_map_status {
10932 /* no duplicate identifier found */
10933 OK_TO_PROCESS = 0,
10934
10935 /* this table map must be filtered out */
10936 FILTERED_OUT = 1,
10937
10938 /* identifier mapping table with different properties */
10939 SAME_ID_MAPPING_DIFFERENT_TABLE = 2,
10940
10941 /* a duplicate identifier was found mapping the same table */
10942 SAME_ID_MAPPING_SAME_TABLE = 3,
10943
10944 /*
10945 this table must be filtered out but found an active XA transaction. XA
10946 transactions shouldn't be used with replication filters, until disabling
10947 the XA read only optimization is a supported feature.
10948 */
10949 FILTERED_WITH_XA_ACTIVE = 4
10950 };
10951
10952 /*
10953 Checks if this table map event should be processed or not. First
10954 it checks the filtering rules, and then looks for duplicate identifiers
10955 in the existing list of rli->tables_to_lock.
10956
10957 It checks that there hasn't been any corruption by verifying that there
10958 are no duplicate entries with different properties.
10959
10960 In some cases, some binary logs could get corrupted, showing several
10961 tables mapped to the same table_id, 0 (see: BUG#56226). Thus we do this
10962 early sanity check for such cases and avoid that the server crashes
10963 later.
10964
10965 In some corner cases, the master logs duplicate table map events, i.e.,
10966 same id, same database name, same table name (see: BUG#37137). This is
10967 different from the above as it's the same table that is mapped again
10968 to the same identifier. Thus we cannot just check for same ids and
10969 assume that the event is corrupted we need to check every property.
10970
10971 NOTE: in the event that BUG#37137 ever gets fixed, this extra check
10972 will still be valid because we would need to support old binary
10973 logs anyway.
10974
10975 @param rli The relay log info reference.
10976 @param table_list A list element containing the table to check against.
10977 @return OK_TO_PROCESS
10978 if there was no identifier already in rli->tables_to_lock
10979
10980 FILTERED_OUT
10981 if the event is filtered according to the filtering rules
10982
10983 SAME_ID_MAPPING_DIFFERENT_TABLE
10984 if the same identifier already maps a different table in
10985 rli->tables_to_lock
10986
10987 SAME_ID_MAPPING_SAME_TABLE
10988 if the same identifier already maps the same table in
10989 rli->tables_to_lock.
10990 */
10991 300842 static enum_tbl_map_status check_table_map(Relay_log_info const *rli,
10992 RPL_TABLE_LIST *table_list) {
10993
1/2
✓ Branch 0 taken 301026 times.
✗ Branch 1 not taken.
300842 DBUG_TRACE;
10994 301026 enum_tbl_map_status res = OK_TO_PROCESS;
10995
10996 #ifdef WITH_WSREP
10997 655199 if ((rli->info_thd->slave_thread /* filtering is for slave only */ ||
10998
11/14
✓ Branch 0 taken 53287 times.
✓ Branch 1 taken 247739 times.
✓ Branch 2 taken 53287 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50562 times.
✓ Branch 5 taken 2725 times.
✓ Branch 6 taken 50564 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 50564 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 50562 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 88 times.
✓ Branch 13 taken 300798 times.
599187 (WSREP(rli->info_thd) && rli->info_thd->wsrep_applier)) &&
10999 #else
11000 if (rli->info_thd->slave_thread /* filtering is for slave only */ &&
11001 #endif /* WITH_WSREP */
11002
3/4
✓ Branch 0 taken 298195 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 298170 times.
✓ Branch 3 taken 25 times.
298301 (!rli->rpl_filter->db_ok(table_list->db) ||
11003
3/4
✓ Branch 0 taken 298136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 222 times.
✓ Branch 3 taken 297914 times.
298170 (rli->rpl_filter->is_on() &&
11004
3/4
✓ Branch 0 taken 222 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 159 times.
222 !rli->rpl_filter->tables_ok("", table_list))))
11005
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 84 times.
88 if (rli->info_thd->get_transaction()->xid_state()->has_state(
11006 XID_STATE::XA_ACTIVE))
11007 4 res = FILTERED_WITH_XA_ACTIVE;
11008 else
11009 84 res = FILTERED_OUT;
11010 else {
11011 300798 RPL_TABLE_LIST *ptr = static_cast<RPL_TABLE_LIST *>(rli->tables_to_lock);
11012
3/4
✓ Branch 0 taken 1387 times.
✓ Branch 1 taken 300749 times.
✓ Branch 2 taken 1387 times.
✗ Branch 3 not taken.
302136 for (uint i = 0; ptr && (i < rli->tables_to_lock_count);
11013 1338 ptr = static_cast<RPL_TABLE_LIST *>(ptr->next_local), i++) {
11014
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1338 times.
1387 if (ptr->table_id == table_list->table_id) {
11015 147 if (strcmp(ptr->db, table_list->db) ||
11016
5/6
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 47 times.
96 strcmp(ptr->alias, table_list->table_name) ||
11017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 ptr->lock_descriptor().type !=
11018 TL_WRITE) // the ::do_apply_event always sets TL_WRITE
11019 2 res = SAME_ID_MAPPING_DIFFERENT_TABLE;
11020 else
11021 47 res = SAME_ID_MAPPING_SAME_TABLE;
11022
11023 49 break;
11024 }
11025 }
11026 }
11027
11028
3/8
✓ Branch 0 taken 300968 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 300998 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 300998 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
300886 DBUG_PRINT("debug", ("check of table map ended up with: %u", res));
11029
11030 301035 return res;
11031 300998 }
11032
11033 300855 int Table_map_log_event::do_apply_event(Relay_log_info const *rli) {
11034 RPL_TABLE_LIST *table_list;
11035 char *db_mem, *tname_mem;
11036 const char *ptr;
11037 size_t dummy_len;
11038 void *memory;
11039
1/2
✓ Branch 0 taken 301033 times.
✗ Branch 1 not taken.
300855 DBUG_TRACE;
11040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 301033 times.
301033 assert(rli->info_thd == thd);
11041
11042 /* Step the query id to mark what columns that are actually used. */
11043
1/2
✓ Branch 0 taken 301033 times.
✗ Branch 1 not taken.
301033 thd->set_query_id(next_query_id());
11044
11045 301018 if (!(memory =
11046
2/4
✓ Branch 0 taken 301018 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 301018 times.
301033 my_multi_malloc(key_memory_log_event, MYF(MY_WME), &table_list,
11047 sizeof(RPL_TABLE_LIST), &db_mem, (uint)NAME_LEN + 1,
11048 &tname_mem, (uint)NAME_LEN + 1, NullS)))
11049 return HA_ERR_OUT_OF_MEM;
11050
11051 301018 my_stpcpy(db_mem, m_dbnam.c_str());
11052 300937 my_stpcpy(tname_mem, m_tblnam.c_str());
11053
11054
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 300958 times.
300965 if (lower_case_table_names) {
11055
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_casedn_str(system_charset_info, db_mem);
11056
1/2
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
7 my_casedn_str(system_charset_info, tname_mem);
11057 }
11058
11059 /* rewrite rules changed the database */
11060
4/4
✓ Branch 0 taken 300998 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 300938 times.
601961 if (rli->rpl_filter != nullptr &&
11061
3/4
✓ Branch 0 taken 300950 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 300925 times.
300998 ((ptr = rli->rpl_filter->get_rewrite_db(db_mem, &dummy_len)) != db_mem)) {
11062 25 rli->rpl_filter->get_rewrite_db_statistics()->increase_counter();
11063 25 my_stpcpy(db_mem, ptr);
11064 }
11065
11066 300963 new (table_list) RPL_TABLE_LIST(db_mem, strlen(db_mem), tname_mem,
11067
1/2
✓ Branch 0 taken 301044 times.
✗ Branch 1 not taken.
300963 strlen(tname_mem), tname_mem, TL_WRITE);
11068
11069
3/4
✓ Branch 0 taken 300977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 300960 times.
✓ Branch 3 taken 17 times.
301044 table_list->table_id = DBUG_EVALUATE_IF(
11070 "inject_tblmap_same_id_maps_diff_table", 0, m_table_id.id());
11071 300939 table_list->updating = true;
11072 300939 table_list->required_type = dd::enum_table_type::BASE_TABLE;
11073
3/8
✓ Branch 0 taken 300968 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 300986 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 300986 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
300939 DBUG_PRINT("debug", ("table: %s is mapped to %llu", table_list->table_name,
11074 table_list->table_id.id()));
11075
11076
1/2
✓ Branch 0 taken 301029 times.
✗ Branch 1 not taken.
300986 enum_tbl_map_status tblmap_status = check_table_map(rli, table_list);
11077
2/2
✓ Branch 0 taken 300897 times.
✓ Branch 1 taken 132 times.
301029 if (tblmap_status == OK_TO_PROCESS) {
11078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300897 times.
300897 assert(thd->lex->query_tables != table_list);
11079
11080 /*
11081 Use placement new to construct the table_def instance in the
11082 memory allocated for it inside table_list.
11083
11084 The memory allocated by the table_def structure (i.e., not the
11085 memory allocated *for* the table_def structure) is released
11086 inside Relay_log_info::clear_tables_to_lock() by calling the
11087 table_def destructor explicitly.
11088 */
11089 300897 new (&table_list->m_tabledef)
11090 300883 table_def(m_coltype, m_colcnt, m_field_metadata, m_field_metadata_size,
11091
1/2
✓ Branch 0 taken 300816 times.
✗ Branch 1 not taken.
300897 m_null_bits, m_flags);
11092
11093 300816 table_list->m_tabledef_valid = true;
11094 300816 table_list->m_conv_table = nullptr;
11095 300816 table_list->open_type = OT_BASE_ONLY;
11096
11097 /*
11098 We record in the slave's information that the table should be
11099 locked by linking the table into the list of tables to lock.
11100 */
11101 300816 table_list->next_global = table_list->next_local = rli->tables_to_lock;
11102 300816 const_cast<Relay_log_info *>(rli)->tables_to_lock = table_list;
11103 300816 const_cast<Relay_log_info *>(rli)->tables_to_lock_count++;
11104 /* 'memory' is freed in clear_tables_to_lock */
11105 } else // FILTERED_OUT, SAME_ID_MAPPING_*
11106 {
11107
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 128 times.
132 if (tblmap_status == FILTERED_WITH_XA_ACTIVE) {
11108
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (thd->slave_thread)
11109
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 rli->report(ERROR_LEVEL, ER_XA_REPLICATION_FILTERS, "%s",
11110
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 ER_THD(thd, ER_XA_REPLICATION_FILTERS));
11111 else
11112 /*
11113 For the cases in which a 'BINLOG' statement is set to
11114 execute in a user session
11115 */
11116 my_printf_error(ER_XA_REPLICATION_FILTERS, "%s", MYF(0),
11117 ER_THD(thd, ER_XA_REPLICATION_FILTERS));
11118 }
11119 /*
11120 If mapped already but with different properties, we raise an
11121 error.
11122 If mapped already but with same properties we skip the event.
11123 If filtered out we skip the event.
11124
11125 In all three cases, we need to free the memory previously
11126 allocated.
11127 */
11128
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 126 times.
128 else if (tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE) {
11129 /*
11130 Something bad has happened. We need to stop the slave as strange things
11131 could happen if we proceed: slave crash, wrong table being updated, ...
11132 As a consequence we push an error in this case.
11133 */
11134
11135 char buf[256];
11136
11137 4 snprintf(buf, sizeof(buf),
11138 "Found table map event mapping table id %llu which "
11139 "was already mapped but with different settings.",
11140 2 table_list->table_id.id());
11141
11142
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (thd->slave_thread)
11143
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
11144
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_SLAVE_FATAL_ERROR), buf);
11145 else
11146 /*
11147 For the cases in which a 'BINLOG' statement is set to
11148 execute in a user session
11149 */
11150
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_printf_error(ER_BINLOG_FATAL_ERROR,
11151
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ER_THD(thd, ER_BINLOG_FATAL_ERROR), MYF(0), buf);
11152 }
11153
11154
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
132 my_free(memory);
11155 }
11156
11157 300874 return tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE;
11158 300874 }
11159
11160 247879 Log_event::enum_skip_reason Table_map_log_event::do_shall_skip(
11161 Relay_log_info *rli) {
11162 /*
11163 If the slave skip counter is 1, then we should not start executing
11164 on the next event.
11165 */
11166 247879 return continue_group(rli);
11167 }
11168
11169 440 int Table_map_log_event::do_update_pos(Relay_log_info *rli) {
11170 440 rli->inc_event_relay_log_pos();
11171 440 return 0;
11172 }
11173
11174 4247084 bool Table_map_log_event::write_data_header(Basic_ostream *ostream) {
11175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247113 times.
4247084 assert(m_table_id.is_valid());
11176 uchar buf[Binary_log_event::TABLE_MAP_HEADER_LEN];
11177
2/6
✓ Branch 0 taken 4247112 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4247112 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4247113 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_source", {
11178 int4store(buf + 0, static_cast<uint32>(m_table_id.id()));
11179 int2store(buf + 4, m_flags);
11180 return (wrapper_my_b_safe_write(ostream, buf, 6));
11181 });
11182 4247112 int6store(buf + TM_MAPID_OFFSET, m_table_id.id());
11183 4247013 int2store(buf + TM_FLAGS_OFFSET, m_flags);
11184
1/2
✓ Branch 0 taken 4247151 times.
✗ Branch 1 not taken.
4247099 return (wrapper_my_b_safe_write(ostream, buf,
11185 4247151 Binary_log_event::TABLE_MAP_HEADER_LEN));
11186 }
11187
11188 4247091 bool Table_map_log_event::write_data_body(Basic_ostream *ostream) {
11189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247106 times.
4247091 assert(!m_dbnam.empty());
11190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247128 times.
4247106 assert(!m_tblnam.empty());
11191
11192 uchar dbuf[sizeof(m_dblen) + 1];
11193
1/2
✓ Branch 0 taken 4247141 times.
✗ Branch 1 not taken.
4247128 uchar *const dbuf_end = net_store_length(dbuf, (size_t)m_dblen);
11194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247141 times.
4247141 assert(static_cast<size_t>(dbuf_end - dbuf) <= sizeof(dbuf));
11195
11196 uchar tbuf[sizeof(m_tbllen) + 1];
11197
1/2
✓ Branch 0 taken 4247159 times.
✗ Branch 1 not taken.
4247141 uchar *const tbuf_end = net_store_length(tbuf, (size_t)m_tbllen);
11198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247159 times.
4247159 assert(static_cast<size_t>(tbuf_end - tbuf) <= sizeof(tbuf));
11199
11200 uchar cbuf[sizeof(m_colcnt) + 1];
11201
1/2
✓ Branch 0 taken 4247160 times.
✗ Branch 1 not taken.
4247159 uchar *const cbuf_end = net_store_length(cbuf, (size_t)m_colcnt);
11202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4247160 times.
4247160 assert(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
11203
11204 /*
11205 Store the size of the field metadata.
11206 */
11207 uchar mbuf[2 * sizeof(m_field_metadata_size)];
11208
1/2
✓ Branch 0 taken 4247149 times.
✗ Branch 1 not taken.
4247160 uchar *const mbuf_end = net_store_length(mbuf, m_field_metadata_size);
11209
11210
1/2
✓ Branch 0 taken 4247154 times.
✗ Branch 1 not taken.
4247149 return (wrapper_my_b_safe_write(ostream, dbuf, (size_t)(dbuf_end - dbuf)) ||
11211
2/4
✓ Branch 0 taken 4247161 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247164 times.
✗ Branch 3 not taken.
4247076 wrapper_my_b_safe_write(ostream, (const uchar *)m_dbnam.c_str(),
11212 4247148 m_dblen + 1) ||
11213
2/4
✓ Branch 0 taken 4247155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247155 times.
✗ Branch 3 not taken.
4247164 wrapper_my_b_safe_write(ostream, tbuf, (size_t)(tbuf_end - tbuf)) ||
11214
2/4
✓ Branch 0 taken 4247168 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247168 times.
✗ Branch 3 not taken.
4247139 wrapper_my_b_safe_write(ostream, (const uchar *)m_tblnam.c_str(),
11215 4247155 m_tbllen + 1) ||
11216
3/4
✓ Branch 0 taken 4247167 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247159 times.
✓ Branch 3 taken 8 times.
4247168 wrapper_my_b_safe_write(ostream, cbuf, (size_t)(cbuf_end - cbuf)) ||
11217
2/4
✓ Branch 0 taken 4247172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247173 times.
✗ Branch 3 not taken.
4247159 wrapper_my_b_safe_write(ostream, m_coltype, m_colcnt) ||
11218
2/4
✓ Branch 0 taken 4247172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247173 times.
✗ Branch 3 not taken.
4247173 wrapper_my_b_safe_write(ostream, mbuf, (size_t)(mbuf_end - mbuf)) ||
11219
2/4
✓ Branch 0 taken 4247144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247148 times.
✗ Branch 3 not taken.
4247173 wrapper_my_b_safe_write(ostream, m_field_metadata,
11220 4247182 m_field_metadata_size) ||
11221
4/6
✓ Branch 0 taken 4247148 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4247182 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4247183 times.
✗ Branch 5 not taken.
12741463 wrapper_my_b_safe_write(ostream, m_null_bits, (m_colcnt + 7) / 8) ||
11222
2/4
✓ Branch 0 taken 4247162 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4247166 times.
4247183 wrapper_my_b_safe_write(ostream, (const uchar *)m_metadata_buf.ptr(),
11223 4247166 m_metadata_buf.length()));
11224 }
11225
11226 /**
11227 stores an integer into packed format.
11228
11229 @param[out] str_buf a buffer where the packed integer will be stored.
11230 @param[in] length the integer will be packed.
11231 */
11232 11109155 static inline void store_compressed_length(String &str_buf, ulonglong length) {
11233 // Store Type and packed length
11234 uchar buf[16];
11235
1/2
✓ Branch 0 taken 11109313 times.
✗ Branch 1 not taken.
11109155 uchar *buf_ptr = net_store_length(buf, length);
11236
11237
1/2
✓ Branch 0 taken 11109294 times.
✗ Branch 1 not taken.
11109313 str_buf.append(reinterpret_cast<char *>(buf), buf_ptr - buf);
11238 11109294 }
11239
11240 /**
11241 Write data into str_buf with Type|Length|Value(TLV) format.
11242
11243 @param[out] str_buf a buffer where the field is stored.
11244 @param[in] type type of the field
11245 @param[in] length length of the field value
11246 @param[in] value value of the field
11247 */
11248 7412383 static inline bool write_tlv_field(
11249 String &str_buf,
11250 enum Table_map_log_event::Optional_metadata_field_type type, uint length,
11251 const uchar *value) {
11252 /* type is stored in one byte, so it should never bigger than 255. */
11253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7412383 times.
7412383 assert(static_cast<int>(type) <= 255);
11254 7412383 str_buf.append((char)type);
11255 7412554 store_compressed_length(str_buf, length);
11256 7412544 return str_buf.append(reinterpret_cast<const char *>(value), length);
11257 }
11258
11259 /**
11260 Write data into str_buf with Type|Length|Value(TLV) format.
11261
11262 @param[out] str_buf a buffer where the field is stored.
11263 @param[in] type type of the field
11264 @param[in] value value of the field
11265 */
11266 7412430 static inline bool write_tlv_field(
11267 String &str_buf,
11268 enum Table_map_log_event::Optional_metadata_field_type type,
11269 const String &value) {
11270 7412442 return write_tlv_field(str_buf, type, value.length(),
11271 14825022 reinterpret_cast<const uchar *>(value.ptr()));
11272 }
11273 #endif // MYSQL_SERVER
11274
11275 30294521 static inline bool is_character_type(uint type) {
11276
2/2
✓ Branch 0 taken 16021632 times.
✓ Branch 1 taken 14272889 times.
30294521 switch (type) {
11277 16021632 case MYSQL_TYPE_STRING:
11278 case MYSQL_TYPE_VAR_STRING:
11279 case MYSQL_TYPE_VARCHAR:
11280 case MYSQL_TYPE_BLOB:
11281 16021632 return true;
11282 14272889 default:
11283 14272889 return false;
11284 }
11285 }
11286
11287 290 static inline bool is_enum_or_set_type(uint type) {
11288
4/4
✓ Branch 0 taken 251 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 212 times.
290 return type == MYSQL_TYPE_ENUM || type == MYSQL_TYPE_SET;
11289 }
11290
11291 #ifdef MYSQL_SERVER
11292 16048924 static inline bool is_numeric_field(const Field *field) {
11293 16048924 return has_signedess_information_type(field->binlog_type());
11294 }
11295
11296 30294215 static inline bool is_character_field(const Field *field) {
11297 30294215 return is_character_type(field->real_type());
11298 }
11299
11300 81 static inline bool is_enum_field(const Field *field) {
11301 81 return field->real_type() == MYSQL_TYPE_ENUM;
11302 }
11303
11304 81 static inline bool is_set_field(const Field *field) {
11305 81 return field->real_type() == MYSQL_TYPE_SET;
11306 }
11307
11308 101 static inline bool is_enum_or_set_field(const Field *field) {
11309 101 return is_enum_or_set_type(field->real_type());
11310 }
11311
11312 16049080 static inline bool is_geometry_field(const Field *field) {
11313 16049080 return field->real_type() == MYSQL_TYPE_GEOMETRY;
11314 }
11315
11316 4246951 void Table_map_log_event::init_metadata_fields() {
11317
1/2
✓ Branch 0 taken 4247140 times.
✗ Branch 1 not taken.
4246951 DBUG_TRACE;
11318
3/4
✓ Branch 0 taken 4247036 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4247035 times.
4247140 DBUG_EXECUTE_IF("simulate_no_optional_metadata", return;);
11319
11320 21235159 if (init_signedness_field() ||
11321
5/8
✓ Branch 0 taken 4247007 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4246926 times.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4247084 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8494019 init_charset_field(&is_character_field, DEFAULT_CHARSET,
11322
3/6
✓ Branch 0 taken 4246951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4246979 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4247077 times.
✗ Branch 5 not taken.
8494103 COLUMN_CHARSET) ||
11323
2/4
✓ Branch 0 taken 4246987 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4247039 times.
4246926 init_geometry_type_field()) {
11324 1 m_metadata_buf.length(0);
11325 1 return;
11326 }
11327
11328
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4247066 times.
4247084 if (binlog_row_metadata == BINLOG_ROW_METADATA_FULL) {
11329
3/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
18 if (DBUG_EVALUATE_IF("dont_log_column_name", 0, init_column_name_field()) ||
11330
4/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
36 init_charset_field(&is_enum_or_set_field, ENUM_AND_SET_DEFAULT_CHARSET,
11331 18 ENUM_AND_SET_COLUMN_CHARSET) ||
11332
4/8
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
18 init_set_str_value_field() || init_enum_str_value_field() ||
11333
8/14
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 17 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 17 times.
✓ Branch 12 taken 18 times.
✗ Branch 13 not taken.
54 init_primary_key_field() || init_column_visibility_field()) {
11334 1 m_metadata_buf.length(0);
11335 }
11336 }
11337
1/2
✓ Branch 0 taken 4247140 times.
✗ Branch 1 not taken.
4246924 }
11338
11339 4246992 bool Table_map_log_event::init_signedness_field() {
11340 /* use it to store signed flags, each numeric column take a bit. */
11341 4246992 StringBuffer<128> buf;
11342 4247074 unsigned char flag = 0;
11343 4247074 unsigned char mask = 0x80;
11344
11345
8/14
✓ Branch 0 taken 4247175 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247172 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16049199 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16049191 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20296216 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 20296319 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 16049172 times.
✓ Branch 13 taken 4247144 times.
20296210 for (auto field : this->m_fields) {
11346
3/4
✓ Branch 0 taken 16049085 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7714571 times.
✓ Branch 3 taken 8334514 times.
16049199 if (is_numeric_field(field)) {
11347
1/2
✓ Branch 0 taken 7714593 times.
✗ Branch 1 not taken.
7714571 Field_num *field_num = dynamic_cast<Field_num *>(field);
11348
2/2
✓ Branch 0 taken 153129 times.
✓ Branch 1 taken 7561493 times.
7714571 if (field_num->is_unsigned()) flag |= mask;
11349
11350 7714622 mask >>= 1;
11351
11352 // 8 fields are tested, store the result and clear the flag.
11353
2/2
✓ Branch 0 taken 156058 times.
✓ Branch 1 taken 7558564 times.
7714622 if (mask == 0) {
11354
1/2
✓ Branch 0 taken 156058 times.
✗ Branch 1 not taken.
156058 buf.append(flag);
11355 156058 flag = 0;
11356 156058 mask = 0x80;
11357 }
11358 }
11359 4247144 }
11360
11361 // Stores the signedness flags of last few columns
11362
3/4
✓ Branch 0 taken 4054334 times.
✓ Branch 1 taken 192760 times.
✓ Branch 2 taken 4054224 times.
✗ Branch 3 not taken.
4247094 if (mask != 0x80) buf.append(flag);
11363
11364 // The table has no numeric column, so don't log SIGNEDNESS field
11365
2/2
✓ Branch 0 taken 192199 times.
✓ Branch 1 taken 4054810 times.
4246984 if (buf.is_empty()) return false;
11366
11367
1/2
✓ Branch 0 taken 4054867 times.
✗ Branch 1 not taken.
4054810 return write_tlv_field(m_metadata_buf, SIGNEDNESS, buf);
11368 4247066 }
11369
11370 4247023 bool Table_map_log_event::init_charset_field(
11371 std::function<bool(const Field *)> include_type,
11372 Optional_metadata_field_type default_charset_type,
11373 Optional_metadata_field_type column_charset_type) {
11374
3/4
✓ Branch 0 taken 4247055 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4247054 times.
4247023 DBUG_EXECUTE_IF("simulate_init_charset_field_error", return true;);
11375
11376 4247054 std::map<uint, uint> collation_map;
11377 // For counting characters columns
11378 4247107 uint char_col_cnt = 0;
11379
11380 /* Find the collation number used by most fields */
11381
8/14
✓ Branch 0 taken 4247170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247166 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16049238 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16049288 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20296325 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 20296412 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 16049227 times.
✓ Branch 13 taken 4247178 times.
20296349 for (auto field : this->m_fields) {
11382
3/4
✓ Branch 0 taken 16049245 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8010834 times.
✓ Branch 3 taken 8038411 times.
16049238 if (include_type(field)) {
11383
1/2
✓ Branch 0 taken 8010834 times.
✗ Branch 1 not taken.
8010834 Field_str *field_str = dynamic_cast<Field_str *>(field);
11384
11385
2/4
✓ Branch 0 taken 8010855 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8010831 times.
✗ Branch 3 not taken.
8010834 collation_map[field_str->charset()->number]++;
11386 8010831 char_col_cnt++;
11387 }
11388 4247178 }
11389
11390
2/2
✓ Branch 0 taken 995928 times.
✓ Branch 1 taken 3251218 times.
4247146 if (char_col_cnt == 0) return false;
11391
11392 /* Find the most used collation */
11393 3251218 uint most_used_collation = 0;
11394 3251218 uint most_used_count = 0;
11395 3251218 for (std::map<uint, uint>::iterator it = collation_map.begin();
11396
2/2
✓ Branch 0 taken 3461020 times.
✓ Branch 1 taken 3251207 times.
6712242 it != collation_map.end(); it++) {
11397
2/2
✓ Branch 0 taken 3286323 times.
✓ Branch 1 taken 174701 times.
3461020 if (it->second > most_used_count) {
11398 3286323 most_used_count = it->second;
11399 3286323 most_used_collation = it->first;
11400 }
11401 }
11402
11403 /*
11404 Comparing length of COLUMN_CHARSET field and COLUMN_CHARSET_WITH_DEFAULT
11405 field to decide which field should be logged.
11406
11407 Length of COLUMN_CHARSET = character column count * collation id size.
11408 Length of COLUMN_CHARSET_WITH_DEFAULT =
11409 default collation_id size + count of columns not use default charset *
11410 (column index size + collation id size)
11411
11412 Assume column index just uses 1 byte and collation number also uses 1 byte.
11413 */
11414
2/2
✓ Branch 0 taken 147072 times.
✓ Branch 1 taken 3104135 times.
3251207 if (char_col_cnt * 1 < (1 + (char_col_cnt - most_used_count) * 2)) {
11415 147072 StringBuffer<512> buf;
11416
11417 /*
11418 Stores character set information into COLUMN_CHARSET format,
11419 character sets of all columns are stored one by one.
11420 -----------------------------------------
11421 | Charset number | .... |Charset number |
11422 -----------------------------------------
11423 */
11424
8/14
✓ Branch 0 taken 147072 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 147072 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 607362 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 607363 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 754435 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 754435 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 607362 times.
✓ Branch 13 taken 147072 times.
754435 for (auto field : this->m_fields) {
11425
3/4
✓ Branch 0 taken 607363 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 302833 times.
✓ Branch 3 taken 304530 times.
607362 if (include_type(field)) {
11426
1/2
✓ Branch 0 taken 302833 times.
✗ Branch 1 not taken.
302833 Field_str *field_str = dynamic_cast<Field_str *>(field);
11427
11428
2/4
✓ Branch 0 taken 302833 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 302833 times.
✗ Branch 3 not taken.
302833 store_compressed_length(buf, field_str->charset()->number);
11429 }
11430 147072 }
11431
1/2
✓ Branch 0 taken 147073 times.
✗ Branch 1 not taken.
147073 return write_tlv_field(m_metadata_buf, column_charset_type, buf);
11432 147073 } else {
11433 3104135 StringBuffer<512> buf;
11434 3104139 uint char_column_index = 0;
11435 3104139 uint default_collation = most_used_collation;
11436
11437 /*
11438 Stores character set information into DEFAULT_CHARSET format,
11439 First stores the default character set, and then stores the character
11440 sets different to default character with their column index one by one.
11441 --------------------------------------------------------
11442 | Default Charset | Col Index | Charset number | ... |
11443 --------------------------------------------------------
11444 */
11445
11446 // Store the default collation number
11447
1/2
✓ Branch 0 taken 3104145 times.
✗ Branch 1 not taken.
3104139 store_compressed_length(buf, default_collation);
11448
11449
8/14
✓ Branch 0 taken 3104146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3104146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13637978 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13637985 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16742117 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 16742124 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 13637977 times.
✓ Branch 13 taken 3104144 times.
16742128 for (auto field : this->m_fields) {
11450
3/4
✓ Branch 0 taken 13637973 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7708031 times.
✓ Branch 3 taken 5929942 times.
13637978 if (include_type(field)) {
11451
1/2
✓ Branch 0 taken 7708031 times.
✗ Branch 1 not taken.
7708031 Field_str *field_str = dynamic_cast<Field_str *>(field);
11452
11453
3/4
✓ Branch 0 taken 7708045 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85414 times.
✓ Branch 3 taken 7622631 times.
7708031 if (field_str->charset()->number != default_collation) {
11454
1/2
✓ Branch 0 taken 85414 times.
✗ Branch 1 not taken.
85414 store_compressed_length(buf, char_column_index);
11455
2/4
✓ Branch 0 taken 85413 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85410 times.
✗ Branch 3 not taken.
85414 store_compressed_length(buf, field_str->charset()->number);
11456 }
11457 7708041 char_column_index++;
11458 }
11459 3104144 }
11460
1/2
✓ Branch 0 taken 3104146 times.
✗ Branch 1 not taken.
3104145 return write_tlv_field(m_metadata_buf, default_charset_type, buf);
11461 3104146 }
11462 4247131 }
11463
11464 17 bool Table_map_log_event::init_column_name_field() {
11465 17 StringBuffer<2048> buf;
11466
11467
8/14
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 77 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 77 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 94 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 94 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 77 times.
✓ Branch 13 taken 17 times.
94 for (auto field : this->m_fields) {
11468 77 size_t len = strlen(field->field_name);
11469
11470
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 store_compressed_length(buf, len);
11471
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 buf.append(field->field_name, len);
11472 17 }
11473
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
34 return write_tlv_field(m_metadata_buf, COLUMN_NAME, buf);
11474 17 }
11475
11476 18 bool Table_map_log_event::init_set_str_value_field() {
11477 18 StringBuffer<1024> buf;
11478
11479 /*
11480 SET string values are stored in the same format:
11481 ----------------------------------------------
11482 | Value number | value1 len | value 1| .... | // first SET column
11483 ----------------------------------------------
11484 | Value number | value1 len | value 1| .... | // second SET column
11485 ----------------------------------------------
11486 */
11487
8/14
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 81 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 99 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 99 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 81 times.
✓ Branch 13 taken 18 times.
99 for (auto field : this->m_fields) {
11488
3/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 74 times.
81 if (is_set_field(field)) {
11489
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 TYPELIB *typelib = dynamic_cast<Field_set *>(field)->typelib;
11490
11491
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 store_compressed_length(buf, typelib->count);
11492
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 7 times.
28 for (unsigned int i = 0; i < typelib->count; i++) {
11493
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 store_compressed_length(buf, typelib->type_lengths[i]);
11494
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 buf.append(typelib->type_names[i], typelib->type_lengths[i]);
11495 }
11496 }
11497 18 }
11498
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
18 if (buf.length() > 0)
11499
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return write_tlv_field(m_metadata_buf, SET_STR_VALUE, buf);
11500 16 return false;
11501 18 }
11502
11503 18 bool Table_map_log_event::init_enum_str_value_field() {
11504 18 StringBuffer<1024> buf;
11505
11506 /* ENUM is same to SET columns, see comment in init_set_str_value_field */
11507
8/14
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 81 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 99 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 99 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 81 times.
✓ Branch 13 taken 18 times.
99 for (auto field : this->m_fields) {
11508
3/4
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 74 times.
81 if (is_enum_field(field)) {
11509
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 TYPELIB *typelib = dynamic_cast<Field_enum *>(field)->typelib;
11510
11511
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 store_compressed_length(buf, typelib->count);
11512
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 7 times.
28 for (unsigned int i = 0; i < typelib->count; i++) {
11513
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 store_compressed_length(buf, typelib->type_lengths[i]);
11514
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 buf.append(typelib->type_names[i], typelib->type_lengths[i]);
11515 }
11516 }
11517 18 }
11518
11519
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
18 if (buf.length() > 0)
11520
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return write_tlv_field(m_metadata_buf, ENUM_STR_VALUE, buf);
11521 16 return false;
11522 18 }
11523
11524 4246862 bool Table_map_log_event::init_geometry_type_field() {
11525 4246862 StringBuffer<256> buf;
11526
11527 /* Geometry type of geometry columns is stored one by one as packed length */
11528
8/14
✓ Branch 0 taken 4247161 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4247159 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16049225 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16049214 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20296147 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 20296321 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 16049202 times.
✓ Branch 13 taken 4247129 times.
20296130 for (auto field : this->m_fields) {
11529
3/4
✓ Branch 0 taken 16049096 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 118840 times.
✓ Branch 3 taken 15930256 times.
16049225 if (is_geometry_field(field)) {
11530
1/2
✓ Branch 0 taken 118840 times.
✗ Branch 1 not taken.
118840 int type = dynamic_cast<Field_geom *>(field)->geom_type;
11531
3/4
✓ Branch 0 taken 118840 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 118837 times.
118840 DBUG_EXECUTE_IF("inject_invalid_geometry_type", type = 100;);
11532
1/2
✓ Branch 0 taken 118840 times.
✗ Branch 1 not taken.
118840 store_compressed_length(buf, type);
11533 }
11534 4247129 }
11535
11536
2/2
✓ Branch 0 taken 106397 times.
✓ Branch 1 taken 4140728 times.
4247125 if (buf.length() > 0)
11537
1/2
✓ Branch 0 taken 106397 times.
✗ Branch 1 not taken.
106397 return write_tlv_field(m_metadata_buf, GEOMETRY_TYPE, buf);
11538 4140728 return false;
11539 4247125 }
11540
11541 18 bool Table_map_log_event::init_primary_key_field() {
11542
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 17 times.
18 DBUG_EXECUTE_IF("simulate_init_primary_key_field_error", return true;);
11543
11544
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
17 if (unlikely(m_table->s->is_missing_primary_key())) return false;
11545
11546 // If any key column uses prefix like KEY(c1(10)) */
11547 4 bool has_prefix = false;
11548 4 KEY *pk = m_table->key_info + m_table->s->primary_key;
11549
11550
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(pk->user_defined_key_parts > 0);
11551
11552 /* Check if any key column uses prefix */
11553
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11554 6 KEY_PART_INFO *key_part = pk->key_part + i;
11555 12 if (key_part->length !=
11556
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 m_table->field[key_part->fieldnr - 1]->key_length()) {
11557 2 has_prefix = true;
11558 2 break;
11559 }
11560 }
11561
11562 4 StringBuffer<128> buf;
11563
11564
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!has_prefix) {
11565 /* Index of PK columns are stored one by one. */
11566
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11567 4 KEY_PART_INFO *key_part = pk->key_part + i;
11568
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 store_compressed_length(buf, key_part->fieldnr - 1);
11569 }
11570
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return write_tlv_field(m_metadata_buf, SIMPLE_PRIMARY_KEY, buf);
11571 } else {
11572 /* Index of PK columns are stored with a prefix length one by one. */
11573
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11574 6 KEY_PART_INFO *key_part = pk->key_part + i;
11575 6 size_t prefix = 0;
11576
11577
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 store_compressed_length(buf, key_part->fieldnr - 1);
11578
11579 // Store character length but not octet length
11580 12 if (key_part->length !=
11581
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 m_table->field[key_part->fieldnr - 1]->key_length())
11582
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 prefix = key_part->length / key_part->field->charset()->mbmaxlen;
11583
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 store_compressed_length(buf, prefix);
11584 }
11585
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return write_tlv_field(m_metadata_buf, PRIMARY_KEY_WITH_PREFIX, buf);
11586 }
11587 4 }
11588
11589 17 bool Table_map_log_event::init_column_visibility_field() {
11590 /*
11591 Buffer to store column visibility. Each column take a bit. Bit is set if
11592 column is visible.
11593 */
11594 17 StringBuffer<128> buf;
11595 17 unsigned char flags = 0;
11596 17 unsigned char mask = 0x80;
11597
11598
8/14
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 80 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 80 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 97 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 97 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 80 times.
✓ Branch 13 taken 17 times.
97 for (auto field : this->m_fields) {
11599
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 7 times.
80 if (!field->is_hidden_by_user()) flags |= mask;
11600 80 mask >>= 1;
11601
11602 // 8 columns are tested. Store the result and clear the flag.
11603
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 77 times.
80 if (mask == 0) {
11604
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 buf.append(flags);
11605 3 flags = 0;
11606 3 mask = 0x80;
11607 }
11608 17 }
11609
11610 // Store the flag for last few columns.
11611
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
17 if (mask != 0x80) buf.append(flags);
11612
11613
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
34 return write_tlv_field(m_metadata_buf, COLUMN_VISIBILITY, buf);
11614 17 }
11615
11616 /*
11617 Print some useful information for the SHOW BINARY LOG information
11618 field.
11619 */
11620
11621 34989 int Table_map_log_event::pack_info(Protocol *protocol) {
11622 char buf[256];
11623 34989 size_t bytes = snprintf(buf, sizeof(buf), "table_id: %llu (%s.%s)",
11624 34989 m_table_id.id(), m_dbnam.c_str(), m_tblnam.c_str());
11625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34989 times.
34989 assert(bytes < 256);
11626
1/2
✓ Branch 0 taken 34989 times.
✗ Branch 1 not taken.
34989 protocol->store_string(buf, bytes, &my_charset_bin);
11627 34989 return 0;
11628 }
11629 #endif // MYSQL_SERVER
11630
11631 #ifndef MYSQL_SERVER
11632 36130 void Table_map_log_event::print(FILE *,
11633 PRINT_EVENT_INFO *print_event_info) const {
11634
2/2
✓ Branch 0 taken 36128 times.
✓ Branch 1 taken 2 times.
36130 if (!print_event_info->short_form) {
11635 36128 print_header(&print_event_info->head_cache, print_event_info, true);
11636 36128 my_b_printf(&print_event_info->head_cache,
11637 "\tTable_map: `%s`.`%s` mapped to number %llu\n",
11638 m_dbnam.c_str(), m_tblnam.c_str(), m_table_id.id());
11639
11640
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 36091 times.
36128 if (print_event_info->print_table_metadata) {
11641 37 Optional_metadata_fields fields(m_optional_metadata,
11642
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 m_optional_metadata_len);
11643
11644
3/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
37 if (m_optional_metadata) assert(fields.is_valid);
11645
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 print_columns(&print_event_info->head_cache, fields);
11646
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 print_primary_key(&print_event_info->head_cache, fields);
11647 37 }
11648
11649 36128 print_base64(&print_event_info->body_cache, print_event_info, true);
11650 }
11651 36130 }
11652
11653 /**
11654 return the string name of a type.
11655
11656 @param[in] type type of a column
11657 @param[in,out] meta_ptr the meta_ptr of the column. If the type doesn't have
11658 metadata, it will not change meta_ptr, otherwise
11659 meta_ptr will be moved to the end of the column's
11660 metadat.
11661 @param[in] cs charset of the column if it is a character column.
11662 @param[out] typestr buffer to storing the string name of the type
11663 @param[in] typestr_length length of typestr
11664 @param[in] geometry_type internal geometry_type
11665 */
11666 177 static void get_type_name(uint type, unsigned char **meta_ptr,
11667 const CHARSET_INFO *cs, char *typestr,
11668 uint typestr_length, unsigned int geometry_type) {
11669
22/23
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 17 times.
✓ Branch 16 taken 17 times.
✓ Branch 17 taken 16 times.
✓ Branch 18 taken 10 times.
✓ Branch 19 taken 21 times.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 25 times.
✓ Branch 22 taken 1 times.
177 switch (type) {
11670 41 case MYSQL_TYPE_LONG:
11671 41 snprintf(typestr, typestr_length, "%s", "INT");
11672 41 break;
11673 case MYSQL_TYPE_BOOL:
11674 snprintf(typestr, typestr_length, "BOOLEAN");
11675 break;
11676 3 case MYSQL_TYPE_TINY:
11677 3 snprintf(typestr, typestr_length, "TINYINT");
11678 3 break;
11679 2 case MYSQL_TYPE_SHORT:
11680 2 snprintf(typestr, typestr_length, "SMALLINT");
11681 2 break;
11682 2 case MYSQL_TYPE_INT24:
11683 2 snprintf(typestr, typestr_length, "MEDIUMINT");
11684 2 break;
11685 3 case MYSQL_TYPE_LONGLONG:
11686 3 snprintf(typestr, typestr_length, "BIGINT");
11687 3 break;
11688 2 case MYSQL_TYPE_NEWDECIMAL:
11689 2 snprintf(typestr, typestr_length, "DECIMAL(%d,%d)", (*meta_ptr)[0],
11690 2 (*meta_ptr)[1]);
11691 2 (*meta_ptr) += 2;
11692 2 break;
11693 3 case MYSQL_TYPE_FLOAT:
11694 3 snprintf(typestr, typestr_length, "FLOAT");
11695 3 (*meta_ptr)++;
11696 3 break;
11697 2 case MYSQL_TYPE_DOUBLE:
11698 2 snprintf(typestr, typestr_length, "DOUBLE");
11699 2 (*meta_ptr)++;
11700 2 break;
11701 2 case MYSQL_TYPE_BIT:
11702 2 snprintf(typestr, typestr_length, "BIT(%d)",
11703 2 (((*meta_ptr)[0])) + (*meta_ptr)[1] * 8);
11704 2 (*meta_ptr) += 2;
11705 2 break;
11706 2 case MYSQL_TYPE_TIMESTAMP2:
11707
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (**meta_ptr != 0)
11708 1 snprintf(typestr, typestr_length, "TIMESTAMP(%d)", **meta_ptr);
11709 else
11710 1 snprintf(typestr, typestr_length, "TIMESTAMP");
11711 2 (*meta_ptr)++;
11712 2 break;
11713 2 case MYSQL_TYPE_DATETIME2:
11714
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (**meta_ptr != 0)
11715 1 snprintf(typestr, typestr_length, "DATETIME(%d)", **meta_ptr);
11716 else
11717 1 snprintf(typestr, typestr_length, "DATETIME");
11718 2 (*meta_ptr)++;
11719 2 break;
11720 2 case MYSQL_TYPE_TIME2:
11721
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (**meta_ptr != 0)
11722 1 snprintf(typestr, typestr_length, "TIME(%d)", **meta_ptr);
11723 else
11724 1 snprintf(typestr, typestr_length, "TIME");
11725 2 (*meta_ptr)++;
11726 2 break;
11727 1 case MYSQL_TYPE_NEWDATE:
11728 case MYSQL_TYPE_DATE:
11729 1 snprintf(typestr, typestr_length, "DATE");
11730 1 break;
11731 2 case MYSQL_TYPE_YEAR:
11732 2 snprintf(typestr, typestr_length, "YEAR");
11733 2 break;
11734 17 case MYSQL_TYPE_ENUM:
11735 17 snprintf(typestr, typestr_length, "ENUM");
11736 17 (*meta_ptr) += 2;
11737 17 break;
11738 17 case MYSQL_TYPE_SET:
11739 17 snprintf(typestr, typestr_length, "SET");
11740 17 (*meta_ptr) += 2;
11741 17 break;
11742 16 case MYSQL_TYPE_BLOB: {
11743
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 5 times.
16 bool is_text = (cs && cs->number != my_charset_bin.number);
11744 16 const char *names[5][2] = {{"INVALID_BLOB(%d)", "INVALID_TEXT(%d)"},
11745 {"TINYBLOB", "TINYTEXT"},
11746 {"BLOB", "TEXT"},
11747 {"MEDIUMBLOB", "MEDIUMTEXT"},
11748 {"LONGBLOB", "LONGTEXT"}};
11749 16 unsigned char size = **meta_ptr;
11750
11751
3/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 15 times.
16 if (size == 0 || size > 4)
11752 1 snprintf(typestr, typestr_length, names[0][is_text], size);
11753 else
11754 15 snprintf(typestr, typestr_length, "%s", names[**meta_ptr][is_text]);
11755
11756 16 (*meta_ptr)++;
11757 16 } break;
11758 10 case MYSQL_TYPE_VARCHAR:
11759 case MYSQL_TYPE_VAR_STRING:
11760
3/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 1 times.
10 if (cs && cs->number != my_charset_bin.number)
11761 9 snprintf(typestr, typestr_length, "VARCHAR(%d)",
11762 9 uint2korr(*meta_ptr) / cs->mbmaxlen);
11763 else
11764 1 snprintf(typestr, typestr_length, "VARBINARY(%d)",
11765 1 uint2korr(*meta_ptr));
11766
11767 10 (*meta_ptr) += 2;
11768 10 break;
11769 21 case MYSQL_TYPE_STRING: {
11770 21 uint byte0 = (*meta_ptr)[0];
11771 21 uint byte1 = (*meta_ptr)[1];
11772 21 uint len = (((byte0 & 0x30) ^ 0x30) << 4) | byte1;
11773
11774
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 1 times.
21 if (cs && cs->number != my_charset_bin.number)
11775 17 snprintf(typestr, typestr_length, "CHAR(%d)", len / cs->mbmaxlen);
11776 else
11777 4 snprintf(typestr, typestr_length, "BINARY(%d)", len);
11778
11779 21 (*meta_ptr) += 2;
11780 21 } break;
11781 1 case MYSQL_TYPE_JSON:
11782 1 snprintf(typestr, typestr_length, "JSON");
11783 1 (*meta_ptr)++;
11784 1 break;
11785 25 case MYSQL_TYPE_GEOMETRY: {
11786 25 const char *names[8] = {
11787 "GEOMETRY", "POINT", "LINESTRING", "POLYGON",
11788 "MULTIPOINT", "MULTILINESTRING", "MULTIPOLYGON", "GEOMCOLLECTION"};
11789
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3 times.
25 if (geometry_type < 8)
11790 22 snprintf(typestr, typestr_length, "%s", names[geometry_type]);
11791 else
11792 3 snprintf(typestr, typestr_length, "INVALID_GEOMETRY_TYPE(%u)",
11793 geometry_type);
11794 25 (*meta_ptr)++;
11795 25 } break;
11796 1 case MYSQL_TYPE_INVALID:
11797 default:
11798 1 *typestr = 0;
11799 1 break;
11800 }
11801 177 }
11802
11803 /**
11804 Interface for iterator over charset columns.
11805 */
11806 class Table_map_log_event::Charset_iterator {
11807 public:
11808 typedef Table_map_event::Optional_metadata_fields::Default_charset
11809 Default_charset;
11810 virtual const CHARSET_INFO *next() = 0;
11811 148 virtual ~Charset_iterator() = default;
11812
11813 /**
11814 Factory method to create an instance of the appropriate subclass.
11815 */
11816 static std::unique_ptr<Charset_iterator> create_charset_iterator(
11817 const Default_charset &default_charset,
11818 const std::vector<uint> &column_charset);
11819 };
11820
11821 /**
11822 Implementation of charset iterator for the DEFAULT_CHARSET type.
11823 */
11824 class Table_map_log_event::Default_charset_iterator : public Charset_iterator {
11825 public:
11826 20 Default_charset_iterator(const Default_charset &default_charset)
11827 40 : m_iterator(default_charset.charset_pairs.begin()),
11828 20 m_end(default_charset.charset_pairs.end()),
11829 20 m_column_index(0),
11830 20 m_default_charset_info(
11831
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
40 get_charset(default_charset.default_charset, 0)) {}
11832
11833 44 const CHARSET_INFO *next() override {
11834 const CHARSET_INFO *ret;
11835
6/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 42 times.
44 if (m_iterator != m_end && m_iterator->first == m_column_index) {
11836 2 ret = get_charset(m_iterator->second, 0);
11837 2 m_iterator++;
11838 } else
11839 42 ret = m_default_charset_info;
11840 44 m_column_index++;
11841 44 return ret;
11842 }
11843
11844 private:
11845 std::vector<Optional_metadata_fields::uint_pair>::const_iterator m_iterator,
11846 m_end;
11847 uint m_column_index;
11848 const CHARSET_INFO *m_default_charset_info;
11849 };
11850
11851 /**
11852 Implementation of charset iterator for the COLUMNT_CHARSET type.
11853 */
11854 class Table_map_log_event::Column_charset_iterator : public Charset_iterator {
11855 public:
11856 54 Column_charset_iterator(const std::vector<uint> &column_charset)
11857 54 : m_iterator(column_charset.begin()), m_end(column_charset.end()) {}
11858
11859 37 const CHARSET_INFO *next() override {
11860 37 const CHARSET_INFO *ret = nullptr;
11861
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 22 times.
37 if (m_iterator != m_end) {
11862 15 ret = get_charset(*m_iterator, 0);
11863 15 m_iterator++;
11864 }
11865 37 return ret;
11866 }
11867
11868 private:
11869 std::vector<uint>::const_iterator m_iterator;
11870 std::vector<uint>::const_iterator m_end;
11871 };
11872
11873 std::unique_ptr<Table_map_log_event::Charset_iterator>
11874 74 Table_map_log_event::Charset_iterator::create_charset_iterator(
11875 const Default_charset &default_charset,
11876 const std::vector<uint> &column_charset) {
11877
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 54 times.
74 if (!default_charset.empty())
11878 return std::unique_ptr<Charset_iterator>(
11879
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 new Default_charset_iterator(default_charset));
11880 else
11881 return std::unique_ptr<Charset_iterator>(
11882 54 new Column_charset_iterator(column_charset));
11883 }
11884
11885 37 void Table_map_log_event::print_columns(
11886 IO_CACHE *file, const Optional_metadata_fields &fields) const {
11887 37 unsigned char *field_metadata_ptr = m_field_metadata;
11888 37 std::vector<bool>::const_iterator signedness_it = fields.m_signedness.begin();
11889
11890 std::unique_ptr<Charset_iterator> charset_it =
11891 37 Charset_iterator::create_charset_iterator(fields.m_default_charset,
11892
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 fields.m_column_charset);
11893 std::unique_ptr<Charset_iterator> enum_and_set_charset_it =
11894 Charset_iterator::create_charset_iterator(
11895 37 fields.m_enum_and_set_default_charset,
11896
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 fields.m_enum_and_set_column_charset);
11897 std::vector<std::string>::const_iterator col_names_it =
11898 37 fields.m_column_name.begin();
11899 std::vector<Optional_metadata_fields::str_vector>::const_iterator
11900 37 set_str_values_it = fields.m_set_str_value.begin();
11901 std::vector<Optional_metadata_fields::str_vector>::const_iterator
11902 37 enum_str_values_it = fields.m_enum_str_value.begin();
11903 std::vector<unsigned int>::const_iterator geometry_type_it =
11904 37 fields.m_geometry_type.begin();
11905 37 uint geometry_type = 0;
11906 std::vector<bool>::const_iterator column_visibility_it =
11907 37 fields.m_column_visibility.begin();
11908
11909
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 my_b_printf(file, "# Columns(");
11910
11911
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 37 times.
214 for (unsigned long i = 0; i < m_colcnt; i++) {
11912 177 uint real_type = m_coltype[i];
11913
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 122 times.
177 if (real_type == MYSQL_TYPE_STRING &&
11914
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 17 times.
55 (*field_metadata_ptr == MYSQL_TYPE_ENUM ||
11915
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 21 times.
38 *field_metadata_ptr == MYSQL_TYPE_SET))
11916 34 real_type = *field_metadata_ptr;
11917
11918 // Get current column's collation id if it is a character, enum,
11919 // or set column
11920 177 const CHARSET_INFO *cs = nullptr;
11921
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 130 times.
177 if (is_character_type(real_type))
11922
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 cs = charset_it->next();
11923
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 96 times.
130 else if (is_enum_or_set_type(real_type))
11924
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 cs = enum_and_set_charset_it->next();
11925
11926 // Print column name
11927
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 93 times.
177 if (col_names_it != fields.m_column_name.end()) {
11928
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 pretty_print_identifier(file, col_names_it->c_str(),
11929 col_names_it->size());
11930
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 my_b_printf(file, " ");
11931 84 col_names_it++;
11932 }
11933
11934 // update geometry_type for geometry columns
11935
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 152 times.
177 if (real_type == MYSQL_TYPE_GEOMETRY) {
11936 25 geometry_type = (geometry_type_it != fields.m_geometry_type.end())
11937
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 1 times.
25 ? *geometry_type_it++
11938 : 0;
11939 }
11940
11941 // print column type
11942 177 const uint TYPE_NAME_LEN = 100;
11943 char type_name[TYPE_NAME_LEN];
11944 177 get_type_name(real_type, &field_metadata_ptr, cs, type_name, TYPE_NAME_LEN,
11945 geometry_type);
11946
11947
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 176 times.
177 if (type_name[0] == '\0') {
11948
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_b_printf(file, "INVALID_TYPE(%d)", real_type);
11949 1 continue;
11950 }
11951
1/2
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
176 my_b_printf(file, "%s", type_name);
11952
11953 // Print UNSIGNED for numeric column
11954 176 enum_field_types field_type_code = static_cast<enum_field_types>(real_type);
11955
4/4
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 116 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 2 times.
236 if (has_signedess_information_type(field_type_code) &&
11956
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 118 times.
236 signedness_it != fields.m_signedness.end()) {
11957
6/6
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 38 times.
58 if (*signedness_it == true &&
11958 // the UNSIGNED modifier is encoded for YEAR but not used
11959 field_type_code != MYSQL_TYPE_YEAR)
11960
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 my_b_printf(file, " UNSIGNED");
11961 58 signedness_it++;
11962 }
11963
11964 // if the column is not marked as 'null', print 'not null'
11965
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 149 times.
176 if (!(m_null_bits[(i / 8)] & (1 << (i % 8))))
11966
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 my_b_printf(file, " NOT NULL");
11967
11968 // Print string values of SET and ENUM column
11969 176 const Optional_metadata_fields::str_vector *str_values = nullptr;
11970
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 159 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 9 times.
193 if (real_type == MYSQL_TYPE_ENUM &&
11971
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 168 times.
193 enum_str_values_it != fields.m_enum_str_value.end()) {
11972 8 str_values = &(*enum_str_values_it);
11973 8 enum_str_values_it++;
11974
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 151 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 9 times.
185 } else if (real_type == MYSQL_TYPE_SET &&
11975
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 160 times.
185 set_str_values_it != fields.m_set_str_value.end()) {
11976 8 str_values = &(*set_str_values_it);
11977 8 set_str_values_it++;
11978 }
11979
11980
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 160 times.
176 if (str_values != nullptr) {
11981 16 const char *separator = "(";
11982 16 for (Optional_metadata_fields::str_vector::const_iterator it =
11983 16 str_values->begin();
11984
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 16 times.
64 it != str_values->end(); it++) {
11985
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 my_b_printf(file, "%s", separator);
11986
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 pretty_print_str(file, it->c_str(), it->size());
11987 48 separator = ", ";
11988 }
11989
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 my_b_printf(file, ")");
11990 }
11991
11992 // Print column character set, except in text columns with binary collation
11993
6/6
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 117 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 52 times.
✓ Branch 5 taken 124 times.
278 if (cs != nullptr &&
11994
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 7 times.
102 (is_enum_or_set_type(real_type) || cs->number != my_charset_bin.number))
11995
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 my_b_printf(file, " CHARSET %s COLLATE %s", cs->csname, cs->m_coll_name);
11996
11997 // If column is invisible then print 'INVISIBLE'.
11998
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 89 times.
176 if (column_visibility_it != fields.m_column_visibility.end()) {
11999
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 73 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
87 if (!(*column_visibility_it)) my_b_printf(file, " INVISIBLE");
12000 87 column_visibility_it++;
12001 }
12002
12003
3/4
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 140 times.
✗ Branch 3 not taken.
176 if (i != m_colcnt - 1) my_b_printf(file, ",\n# ");
12004 }
12005
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 my_b_printf(file, ")");
12006
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 my_b_printf(file, "\n");
12007 37 }
12008
12009 37 void Table_map_log_event::print_primary_key(
12010 IO_CACHE *file, const Optional_metadata_fields &fields) const {
12011
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 32 times.
37 if (!fields.m_primary_key.empty()) {
12012
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_b_printf(file, "# Primary Key(");
12013
12014 std::vector<Optional_metadata_fields::uint_pair>::const_iterator it =
12015 5 fields.m_primary_key.begin();
12016
12017
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for (; it != fields.m_primary_key.end(); it++) {
12018
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
11 if (it != fields.m_primary_key.begin()) my_b_printf(file, ", ");
12019
12020 // Print column name or column index
12021
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if (it->first >= fields.m_column_name.size())
12022
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_b_printf(file, "%u", it->first);
12023 else
12024
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 my_b_printf(file, "%s", fields.m_column_name[it->first].c_str());
12025
12026 // Print prefix length
12027
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
11 if (it->second != 0) my_b_printf(file, "(%u)", it->second);
12028 }
12029
12030
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 my_b_printf(file, ")\n");
12031 }
12032 37 }
12033 #endif
12034
12035 /**************************************************************************
12036 Write_rows_log_event member functions
12037 **************************************************************************/
12038
12039 /*
12040 Constructor used to build an event for writing to the binary log.
12041 */
12042 #if defined(MYSQL_SERVER)
12043 8610910 Write_rows_log_event::Write_rows_log_event(
12044 THD *thd_arg, TABLE *tbl_arg, const Table_id &tid_arg,
12045 8610910 bool is_transactional, const unsigned char *extra_row_ndb_info)
12046 : binary_log::Rows_event(log_bin_use_v1_row_events
12047 ? binary_log::WRITE_ROWS_EVENT_V1
12048 : binary_log::WRITE_ROWS_EVENT),
12049 8610746 Rows_log_event(thd_arg, tbl_arg, tid_arg, tbl_arg->write_set,
12050 is_transactional,
12051 log_bin_use_v1_row_events ? binary_log::WRITE_ROWS_EVENT_V1
12052 : binary_log::WRITE_ROWS_EVENT,
12053
6/9
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4305453 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4305371 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4305393 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4305387 times.
✗ Branch 8 not taken.
8610910 extra_row_ndb_info) {
12054 8610774 common_header->type_code = m_type;
12055 }
12056
12057 41827250 bool Write_rows_log_event::binlog_row_logging_function(
12058 THD *thd_arg, TABLE *table, bool is_transactional,
12059 const uchar *before_record [[maybe_unused]], const uchar *after_record) {
12060 41827250 return thd_arg->binlog_write_row(table, is_transactional, after_record,
12061 41827585 nullptr);
12062 }
12063 #endif
12064
12065 /*
12066 Constructor used by slave to read the event from the binary log.
12067 */
12068 10758638 Write_rows_log_event::Write_rows_log_event(
12069 10758638 const char *buf, const Format_description_event *description_event)
12070 : binary_log::Rows_event(buf, description_event),
12071 Rows_log_event(buf, description_event),
12072
2/4
✓ Branch 0 taken 5379380 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5379341 times.
✗ Branch 3 not taken.
10758638 binary_log::Write_rows_event(buf, description_event) {
12073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5379400 times.
10758682 assert(header()->type_code == m_type);
12074 }
12075
12076 #if defined(MYSQL_SERVER)
12077 310538 int Write_rows_log_event::do_before_row_operations(
12078 const Slave_reporting_capability *const) {
12079 310538 int error = 0;
12080
12081 310538 m_table->file->rpl_before_write_rows();
12082
12083 /*
12084 Increment the global status insert count variable
12085 */
12086
2/2
✓ Branch 0 taken 261421 times.
✓ Branch 1 taken 49279 times.
310563 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_INSERT]++;
12087
12088 /*
12089 Let storage engines treat this event as an INSERT command.
12090
12091 Set 'sql_command' as SQLCOM_INSERT after the tables are locked.
12092 When locking the tables, it should be SQLCOM_END.
12093 THD::decide_logging_format which is called from "lock tables"
12094 assumes that row_events will have 'sql_command' as SQLCOM_END.
12095 */
12096 310700 thd->lex->sql_command = SQLCOM_INSERT;
12097
12098
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 310735 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
310700 DBUG_EXECUTE_IF(
12099 "crash_on_transactional_ddl_insert",
12100 if (thd->m_transactional_ddl.inited()) { DBUG_SUICIDE(); });
12101
12102 /**
12103 todo: to introduce a property for the event (handler?) which forces
12104 applying the event in the replace (idempotent) fashion.
12105 */
12106
4/4
✓ Branch 0 taken 310680 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 310713 times.
621461 if ((rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT) ||
12107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 310713 times.
310680 (m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)) {
12108 /*
12109 We are using REPLACE semantics and not INSERT IGNORE semantics
12110 when writing rows, that is: new rows replace old rows. We need to
12111 inform the storage engine that it should use this behaviour.
12112 */
12113
12114 /* Tell the storage engine that we are using REPLACE semantics. */
12115 68 thd->lex->duplicates = DUP_REPLACE;
12116
12117 /*
12118 Pretend we're executing a REPLACE command: this is needed for
12119 InnoDB and NDB Cluster since they are not (properly) checking the
12120 lex->duplicates flag.
12121 */
12122 68 thd->lex->sql_command = SQLCOM_REPLACE;
12123 /*
12124 Do not raise the error flag in case of hitting to an unique attribute
12125 */
12126 68 m_table->file->ha_extra(HA_EXTRA_IGNORE_DUP_KEY);
12127 /*
12128 NDB specific: update from ndb master wrapped as Write_rows
12129 so that the event should be applied to replace slave's row
12130 */
12131 68 m_table->file->ha_extra(HA_EXTRA_WRITE_CAN_REPLACE);
12132 /*
12133 NDB specific: if update from ndb master wrapped as Write_rows
12134 does not find the row it's assumed idempotent binlog applying
12135 is taking place; don't raise the error.
12136 */
12137 68 m_table->file->ha_extra(HA_EXTRA_IGNORE_NO_KEY);
12138 /*
12139 TODO: the cluster team (Tomas?) says that it's better if the engine knows
12140 how many rows are going to be inserted, then it can allocate needed memory
12141 from the start.
12142 */
12143 }
12144
12145 /* Honor next number column if present */
12146 310781 m_table->next_number_field = m_table->found_next_number_field;
12147 /*
12148 * Fixed Bug#45999, In RBR, Store engine of Slave auto-generates new
12149 * sequence numbers for auto_increment fields if the values of them are 0.
12150 * If generateing a sequence number is decided by the values of
12151 * table->autoinc_field_has_explicit_non_null_value and SQL_MODE(if
12152 * includes MODE_NO_AUTO_VALUE_ON_ZERO) in update_auto_increment function.
12153 * SQL_MODE of slave sql thread is always consistency with master's.
12154 * In RBR, auto_increment fields never are NULL, except if the auto_inc
12155 * column exists only on the slave side (i.e., in an extra column
12156 * on the slave's table).
12157 */
12158
2/2
✓ Branch 0 taken 310474 times.
✓ Branch 1 taken 155 times.
310781 if (!is_auto_inc_in_extra_columns())
12159 310474 m_table->autoinc_field_has_explicit_non_null_value = true;
12160 else {
12161 /*
12162 Here we have checked that there is an extra field
12163 on this server's table that has an auto_inc column.
12164
12165 Mark that the auto_increment field is null and mark
12166 the read and write set bits.
12167
12168 (There can only be one AUTO_INC column, it is always
12169 indexed and it cannot have a DEFAULT value).
12170 */
12171 155 m_table->autoinc_field_has_explicit_non_null_value = false;
12172 155 m_table->mark_auto_increment_column();
12173 }
12174
12175 /**
12176 Sets it to ROW_LOOKUP_NOT_NEEDED.
12177 */
12178 310661 decide_row_lookup_algorithm_and_key();
12179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 310626 times.
310624 assert(m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED);
12180
12181 310626 return error;
12182 }
12183
12184 310733 int Write_rows_log_event::do_after_row_operations(
12185 const Slave_reporting_capability *const, int error) {
12186 310733 int local_error = 0;
12187
12188 /**
12189 Clear the write_set bit for auto_inc field that only
12190 existed on the destination table as an extra column.
12191 */
12192
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 310574 times.
310733 if (is_auto_inc_in_extra_columns()) {
12193 187 bitmap_clear_bit(m_table->write_set,
12194 187 m_table->next_number_field->field_index());
12195 187 bitmap_clear_bit(m_table->read_set,
12196 187 m_table->next_number_field->field_index());
12197
12198
1/2
✓ Branch 0 taken 187 times.
✗ Branch 1 not taken.
187 if (get_flags(STMT_END_F)) m_table->file->ha_release_auto_increment();
12199 }
12200 310761 m_table->next_number_field = nullptr;
12201 310761 m_table->autoinc_field_has_explicit_non_null_value = false;
12202
12203 /**
12204 Row based replication for Ndb requires resetting flags after each event.
12205 This is symmetric with do_before_row_operations.
12206 */
12207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 310794 times.
310761 if (m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER) {
12208 m_table->file->ha_extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
12209 m_table->file->ha_extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
12210 }
12211
12212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 310845 times.
310794 if ((local_error = m_table->file->ha_end_bulk_insert())) {
12213 m_table->file->print_error(local_error, MYF(0));
12214 }
12215
12216 310845 m_rows_lookup_algorithm = ROW_LOOKUP_UNDEFINED;
12217 310845 m_table->file->rpl_after_write_rows();
12218
12219
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 310654 times.
310821 return error ? error : local_error;
12220 }
12221
12222 /*
12223 Check if there are more UNIQUE keys after the given key.
12224 */
12225 20 static int last_uniq_key(TABLE *table, uint keyno) {
12226
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 17 times.
20 while (++keyno < table->s->keys)
12227
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (table->key_info[keyno].flags & HA_NOSAME) return 0;
12228 17 return 1;
12229 }
12230
12231 /**
12232 Write the current row into event's table.
12233
12234 The row is located in the row buffer, pointed by @c m_curr_row member.
12235 Number of columns of the row is stored in @c m_width member (it can be
12236 different from the number of columns in the table to which we insert).
12237 Bitmap @c m_cols indicates which columns are present in the row. It is assumed
12238 that event's table is already open and pointed by @c m_table.
12239
12240 If the same record already exists in the table it can be either overwritten
12241 or an error is reported depending on the value of @c overwrite flag
12242 (error reporting not yet implemented). Note that the matching record can be
12243 different from the row we insert if we use primary keys to identify records in
12244 the table.
12245
12246 The row to be inserted can contain values only for selected columns. The
12247 missing columns are filled with default values using @c prepare_record()
12248 function. If a matching record is found in the table and @c overwritte is
12249 true, the missing columns are taken from it.
12250
12251 @param rli Relay log info (needed for row unpacking).
12252 @param overwrite
12253 Shall we overwrite if the row already exists or signal
12254 error (currently ignored).
12255
12256 @returns Error code on failure, 0 on success.
12257
12258 This method, if successful, sets @c m_curr_row_end pointer to point at the
12259 next row in the rows buffer. This is done when unpacking the row to be
12260 inserted.
12261
12262 @note If a matching record is found, it is either updated using
12263 @c ha_update_row() or first deleted and then new record written.
12264 */
12265
12266 2799678 int Write_rows_log_event::write_row(const Relay_log_info *const rli,
12267 const bool overwrite) {
12268
1/2
✓ Branch 0 taken 2799950 times.
✗ Branch 1 not taken.
2799678 DBUG_TRACE;
12269
3/4
✓ Branch 0 taken 2799951 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2799932 times.
✓ Branch 3 taken 19 times.
2799950 assert(m_table != nullptr && thd != nullptr);
12270
12271 2799932 TABLE *table = m_table; // pointer to event's table
12272 int error;
12273 2799932 int keynum = 0;
12274 2799932 char *key = nullptr;
12275
12276 2799932 prepare_record(table, &this->m_local_cols,
12277
1/2
✓ Branch 0 taken 2799951 times.
✗ Branch 1 not taken.
2799932 table->file->ht->db_type != DB_TYPE_NDBCLUSTER);
12278
12279 /* unpack row into table->record[0] */
12280
2/4
✓ Branch 0 taken 2799730 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2799730 times.
2799951 if ((error = unpack_current_row(rli, &m_cols, true /*is AI*/))) return error;
12281
12282 /*
12283 When m_curr_row == m_curr_row_end, it means a row that contains nothing,
12284 so all the pointers shall be pointing to the same address, or else
12285 we have corrupt data and shall throw the error.
12286 */
12287
3/8
✓ Branch 0 taken 2799842 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2799702 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2799702 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2799730 DBUG_PRINT("debug", ("m_rows_buf= %p, m_rows_cur= %p, m_rows_end= %p",
12288 m_rows_buf, m_rows_cur, m_rows_end));
12289
3/8
✓ Branch 0 taken 2799910 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2799921 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2799921 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2799702 DBUG_PRINT("debug", ("m_curr_row= %p, m_curr_row_end= %p", m_curr_row,
12290 m_curr_row_end));
12291
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2799915 times.
2799921 if (m_curr_row == m_curr_row_end &&
12292
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 !((m_rows_buf == m_rows_cur) && (m_rows_cur == m_rows_end))) {
12293 my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0));
12294 return ER_SLAVE_CORRUPT_EVENT;
12295 }
12296
12297 // Invoke check constraints on the unpacked row.
12298
2/4
✓ Branch 0 taken 2799651 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2799651 times.
2799921 if (invoke_table_check_constraints(thd, table))
12299 return ER_CHECK_CONSTRAINT_VIOLATED;
12300
12301
2/2
✓ Branch 0 taken 310603 times.
✓ Branch 1 taken 2489048 times.
2799651 if (m_curr_row == m_rows_buf) {
12302 /* this is the first row to be inserted, we estimate the rows with
12303 the size of the first row and use that value to initialize
12304 storage engine for bulk insertion */
12305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 310603 times.
310603 assert(!(m_curr_row > m_curr_row_end));
12306 310603 ulong estimated_rows = 0;
12307
1/2
✓ Branch 0 taken 310684 times.
✗ Branch 1 not taken.
310603 if (m_curr_row < m_curr_row_end)
12308 310684 estimated_rows =
12309 310684 (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
12310 else if (m_curr_row == m_curr_row_end)
12311 6 estimated_rows = 1;
12312
12313
1/2
✓ Branch 0 taken 310774 times.
✗ Branch 1 not taken.
310603 m_table->file->ha_start_bulk_insert(estimated_rows);
12314 }
12315
12316 /*
12317 Explicitly set the auto_inc to null to make sure that
12318 it gets an auto_generated value.
12319 */
12320
4/6
✓ Branch 0 taken 2799954 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 187 times.
✓ Branch 3 taken 2799767 times.
✓ Branch 4 taken 187 times.
✗ Branch 5 not taken.
2799822 if (is_auto_inc_in_extra_columns()) m_table->next_number_field->set_null();
12321
12322 #ifndef NDEBUG
12323
1/2
✓ Branch 0 taken 2799837 times.
✗ Branch 1 not taken.
2799954 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
12324
7/12
✓ Branch 0 taken 3931159 times.
✓ Branch 1 taken 1138 times.
✓ Branch 2 taken 3932322 times.
✓ Branch 3 taken 2799870 times.
✓ Branch 4 taken 2799881 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2799860 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2799860 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
6732134 DBUG_PRINT_BITSET("debug", "write_set = %s", table->write_set);
12325
6/12
✓ Branch 0 taken 3932306 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3932310 times.
✓ Branch 3 taken 2799864 times.
✓ Branch 4 taken 2799844 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2799905 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2799905 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
6732165 DBUG_PRINT_BITSET("debug", "read_set = %s", table->read_set);
12326 #endif
12327
12328 /*
12329 Try to write record. If a corresponding record already exists in the table,
12330 we try to change it using ha_update_row() if possible. Otherwise we delete
12331 it and repeat the whole process again.
12332
12333 TODO: Add safety measures against infinite looping.
12334 */
12335
12336
1/2
✓ Branch 0 taken 2799965 times.
✗ Branch 1 not taken.
2799905 m_table->mark_columns_per_binlog_row_image(thd);
12337
12338
3/4
✓ Branch 0 taken 2799889 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195 times.
✓ Branch 3 taken 2799694 times.
2799968 while ((error = table->file->ha_write_row(table->record[0]))) {
12339
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 97 times.
183 if (error == HA_ERR_LOCK_DEADLOCK || error == HA_ERR_LOCK_WAIT_TIMEOUT ||
12340
9/10
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 62 times.
✓ Branch 7 taken 20 times.
✓ Branch 8 taken 175 times.
✓ Branch 9 taken 20 times.
378 (keynum = table->file->get_dup_key(error)) < 0 || !overwrite) {
12341
3/8
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 176 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 176 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
175 DBUG_PRINT("info", ("get_dup_key returns %d)", keynum));
12342 /*
12343 Deadlock, waiting for lock or just an error from the handler
12344 such as HA_ERR_FOUND_DUPP_KEY when overwrite is false.
12345 Retrieval of the duplicate key number may fail
12346 - either because the error was not "duplicate key" error
12347 - or because the information which key is not available
12348 */
12349
1/2
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
176 table->file->print_error(error, MYF(0));
12350 176 goto error;
12351 }
12352 /*
12353 key index value is either valid in the range [0-MAX_KEY) or
12354 has value MAX_KEY as a marker for the case when no information
12355 about key can be found. In the last case we have to require
12356 that storage engine has the flag HA_DUPLICATE_POS turned on.
12357 If this invariant is false then assert will crash
12358 the server built in debug mode. For the server that was built
12359 without DEBUG we have additional check for the value of key index
12360 in the code below in order to report about error in any case.
12361 */
12362
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
20 assert(keynum != MAX_KEY ||
12363 (keynum == MAX_KEY &&
12364 (table->file->ha_table_flags() & HA_DUPLICATE_POS)));
12365 /*
12366 We need to retrieve the old row into record[1] to be able to
12367 either update or delete the offending record. We either:
12368
12369 - use ha_rnd_pos() with a row-id (available as dupp_row) to the
12370 offending row, if that is possible (MyISAM and Blackhole), or else
12371
12372 - use ha_index_read_idx_map() with the key that is duplicated, to
12373 retrieve the offending row.
12374 */
12375
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 13 times.
20 if (table->file->ha_table_flags() & HA_DUPLICATE_POS) {
12376
3/8
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7 DBUG_PRINT("info", ("Locating offending record using ha_rnd_pos()"));
12377
12378
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
7 if (table->file->inited && (error = table->file->ha_index_end())) {
12379 table->file->print_error(error, MYF(0));
12380 goto error;
12381 }
12382
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if ((error = table->file->ha_rnd_init(false))) {
12383 table->file->print_error(error, MYF(0));
12384 goto error;
12385 }
12386
12387
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 error = table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
12388
12389
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 table->file->ha_rnd_end();
12390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (error) {
12391 DBUG_PRINT("info", ("ha_rnd_pos() returns error %d", error));
12392 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
12393 table->file->print_error(error, MYF(0));
12394 goto error;
12395 }
12396 } else {
12397
3/8
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
13 DBUG_PRINT("info", ("Locating offending record using index_read_idx()"));
12398
12399
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (key == nullptr) {
12400 13 key = static_cast<char *>(my_alloca(table->s->max_unique_length));
12401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (key == nullptr) {
12402 DBUG_PRINT("info", ("Can't allocate key buffer"));
12403 error = ENOMEM;
12404 goto error;
12405 }
12406 }
12407
12408
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if ((uint)keynum < MAX_KEY) {
12409
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 key_copy((uchar *)key, table->record[0], table->key_info + keynum, 0);
12410
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 error = table->file->ha_index_read_idx_map(
12411 table->record[1], keynum, (const uchar *)key, HA_WHOLE_KEY,
12412 HA_READ_KEY_EXACT);
12413 } else
12414 /*
12415 For the server built in non-debug mode returns error if
12416 handler::get_dup_key() returned MAX_KEY as the value of key index.
12417 */
12418 error = HA_ERR_FOUND_DUPP_KEY;
12419
12420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (error) {
12421 DBUG_PRINT("info",
12422 ("ha_index_read_idx_map() returns %s", HA_ERR(error)));
12423 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
12424 table->file->print_error(error, MYF(0));
12425 goto error;
12426 }
12427 }
12428
12429 /*
12430 Now, record[1] should contain the offending row. That
12431 will enable us to update it or, alternatively, delete it (so
12432 that we can insert the new row afterwards).
12433 */
12434
12435 /*
12436 If row is incomplete we will use the record found to fill
12437 missing columns.
12438 */
12439
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 14 times.
20 if (!get_flags(COMPLETE_ROWS_F)) {
12440 6 restore_record(table, record[1]);
12441
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 error = unpack_current_row(rli, &m_cols, true /*is AI*/);
12442 }
12443
12444 #ifndef NDEBUG
12445
3/8
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
20 DBUG_PRINT("debug", ("preparing for update: before and after image"));
12446
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 DBUG_DUMP("record[1] (before)", table->record[1], table->s->reclength);
12447
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 DBUG_DUMP("record[0] (after)", table->record[0], table->s->reclength);
12448 #endif
12449
12450 /*
12451 REPLACE is defined as either INSERT or DELETE + INSERT. If
12452 possible, we can replace it with an UPDATE, but that will not
12453 work on InnoDB if FOREIGN KEY checks are necessary.
12454
12455 I (Matz) am not sure of the reason for the last_uniq_key()
12456 check as, but I'm guessing that it's something along the
12457 following lines.
12458
12459 Suppose that we got the duplicate key to be a key that is not
12460 the last unique key for the table and we perform an update:
12461 then there might be another key for which the unique check will
12462 fail, so we're better off just deleting the row and inserting
12463 the correct row.
12464 */
12465
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 3 times.
37 if (last_uniq_key(table, keynum) &&
12466
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 !table->s->is_referenced_by_foreign_key()) {
12467
3/8
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
17 DBUG_PRINT("info", ("Updating row using ha_update_row()"));
12468
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
17 error = table->file->ha_update_row(table->record[1], table->record[0]);
12469
2/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
17 switch (error) {
12470 2 case HA_ERR_RECORD_IS_THE_SAME:
12471
3/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 DBUG_PRINT("info", ("ignoring HA_ERR_RECORD_IS_THE_SAME error from"
12472 " ha_update_row()"));
12473 2 error = 0;
12474
12475 17 case 0:
12476 17 break;
12477
12478 default:
12479 DBUG_PRINT("info", ("ha_update_row() returns error %d", error));
12480 table->file->print_error(error, MYF(0));
12481 }
12482
12483 17 goto error;
12484 } else {
12485
3/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
3 DBUG_PRINT("info",
12486 ("Deleting offending row and trying to write new one again"));
12487
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if ((error = table->file->ha_delete_row(table->record[1]))) {
12488 DBUG_PRINT("info", ("ha_delete_row() returns error %d", error));
12489 table->file->print_error(error, MYF(0));
12490 goto error;
12491 }
12492 /* Will retry ha_write_row() with the offending row removed. */
12493 }
12494 }
12495
12496 2799694 error:
12497 2799887 m_table->default_column_bitmaps();
12498 2799918 return error;
12499 2799918 }
12500
12501 2799686 int Write_rows_log_event::do_exec_row(const Relay_log_info *const rli) {
12502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2799686 times.
2799686 assert(m_table != nullptr);
12503
12504 #ifdef WITH_WSREP
12505
6/8
✓ Branch 0 taken 2799737 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2333063 times.
✓ Branch 3 taken 466674 times.
✓ Branch 4 taken 2333102 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2333086 times.
✓ Branch 7 taken 16 times.
2799686 if (WSREP(thd)) {
12506 2333086 THD_STAGE_INFO(thd, stage_wsrep_writing_rows);
12507 4666184 snprintf(thd->wsrep_info, sizeof(thd->wsrep_info),
12508 "wsrep: writing row for write-set (%lld)",
12509 2333101 (long long)wsrep_thd_trx_seqno(thd));
12510
11/20
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 2332977 times.
✓ Branch 2 taken 106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 106 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 106 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 106 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 106 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 106 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 106 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 106 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 106 times.
2333083 WSREP_DEBUG("%s", thd->wsrep_info);
12511 2333083 thd_proc_info(thd, thd->wsrep_info);
12512 }
12513 #endif /* WITH_WSREP */
12514
12515 2799631 int error = write_row(rli, rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT);
12516
12517
4/6
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 2799742 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 177 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2799919 times.
2799913 if (error && !thd->is_error()) {
12518 assert(0);
12519 my_error(ER_UNKNOWN_ERROR, MYF(0));
12520 }
12521
12522 2799919 return error;
12523 }
12524
12525 #endif /* defined(MYSQL_SERVER) */
12526
12527 #ifndef MYSQL_SERVER
12528 24655 void Write_rows_log_event::print(FILE *file,
12529 PRINT_EVENT_INFO *print_event_info) const {
12530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24655 times.
24655 DBUG_EXECUTE_IF("simulate_cache_read_error",
12531 { DBUG_SET("+d,simulate_my_b_fill_error"); });
12532 24655 Rows_log_event::print_helper(file, print_event_info);
12533 24655 }
12534 #endif
12535
12536 /**************************************************************************
12537 Delete_rows_log_event member functions
12538 **************************************************************************/
12539
12540 /*
12541 Constructor used to build an event for writing to the binary log.
12542 */
12543
12544 #ifdef MYSQL_SERVER
12545 216398 Delete_rows_log_event::Delete_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
12546 const Table_id &tid,
12547 bool is_transactional,
12548 216398 const uchar *extra_row_ndb_info)
12549 : binary_log::Rows_event(log_bin_use_v1_row_events
12550 ? binary_log::DELETE_ROWS_EVENT_V1
12551 : binary_log::DELETE_ROWS_EVENT),
12552 216398 Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
12553 log_bin_use_v1_row_events
12554 ? binary_log::DELETE_ROWS_EVENT_V1
12555 : binary_log::DELETE_ROWS_EVENT,
12556 extra_row_ndb_info),
12557
4/9
✗ Branch 0 not taken.
✓ Branch 1 taken 108199 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 108199 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 108199 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 108199 times.
✗ Branch 8 not taken.
216398 binary_log::Delete_rows_event() {
12558 216398 common_header->type_code = m_type;
12559 }
12560
12561 2083635 bool Delete_rows_log_event::binlog_row_logging_function(
12562 THD *thd_arg, TABLE *table, bool is_transactional,
12563 const uchar *before_record, const uchar *after_record [[maybe_unused]]) {
12564 2083635 return thd_arg->binlog_delete_row(table, is_transactional, before_record,
12565 2083635 nullptr);
12566 }
12567
12568 #endif /* #if defined(MYSQL_SERVER) */
12569
12570 /*
12571 Constructor used by slave to read the event from the binary log.
12572 */
12573 109862 Delete_rows_log_event::Delete_rows_log_event(
12574 109862 const char *buf, const Format_description_event *description_event)
12575 : binary_log::Rows_event(buf, description_event),
12576 Rows_log_event(buf, description_event),
12577
2/4
✓ Branch 0 taken 54931 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54931 times.
✗ Branch 3 not taken.
109862 binary_log::Delete_rows_event(buf, description_event) {
12578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54931 times.
109862 assert(header()->type_code == m_type);
12579 }
12580
12581 #if defined(MYSQL_SERVER)
12582
12583 12727 int Delete_rows_log_event::do_before_row_operations(
12584 const Slave_reporting_capability *const) {
12585 12727 int error = 0;
12586
1/2
✓ Branch 0 taken 12727 times.
✗ Branch 1 not taken.
12727 DBUG_TRACE;
12587
1/2
✓ Branch 0 taken 12727 times.
✗ Branch 1 not taken.
12727 m_table->file->rpl_before_delete_rows();
12588 /*
12589 Increment the global status delete count variable
12590 */
12591
2/2
✓ Branch 0 taken 11780 times.
✓ Branch 1 taken 947 times.
12727 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_DELETE]++;
12592
12593 /*
12594 Let storage engines treat this event as a DELETE command.
12595
12596 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
12597 When locking the tables, it should be SQLCOM_END.
12598 THD::decide_logging_format which is called from "lock tables"
12599 assumes that row_events will have 'sql_command' as SQLCOM_END.
12600 */
12601 12727 thd->lex->sql_command = SQLCOM_DELETE;
12602
12603
1/2
✓ Branch 0 taken 12727 times.
✗ Branch 1 not taken.
12727 error = row_operations_scan_and_key_setup();
12604 12727 return error;
12605 12727 }
12606
12607 12727 int Delete_rows_log_event::do_after_row_operations(
12608 const Slave_reporting_capability *const, int error) {
12609
1/2
✓ Branch 0 taken 12727 times.
✗ Branch 1 not taken.
12727 DBUG_TRACE;
12610
1/2
✓ Branch 0 taken 12727 times.
✗ Branch 1 not taken.
12727 error = row_operations_scan_and_key_teardown(error);
12611
1/2
✓ Branch 0 taken 12727 times.
✗ Branch 1 not taken.
12727 m_table->file->rpl_after_delete_rows();
12612 12727 return error;
12613 12727 }
12614
12615 42486 int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli) {
12616 int error;
12617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42486 times.
42486 assert(m_table != nullptr);
12618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42486 times.
42486 if (m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED) {
12619 error = unpack_current_row(rli, &m_cols, false, false);
12620 if (error) return error;
12621 }
12622
12623 #ifdef WITH_WSREP
12624
5/8
✓ Branch 0 taken 42486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2107 times.
✓ Branch 3 taken 40379 times.
✓ Branch 4 taken 2107 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2107 times.
✗ Branch 7 not taken.
42486 if (WSREP(thd)) {
12625 2107 THD_STAGE_INFO(thd, stage_wsrep_deleting_rows);
12626 4214 snprintf(thd->wsrep_info, sizeof(thd->wsrep_info),
12627 "wsrep: deleting row for write-set (%lld)",
12628 2107 (long long)wsrep_thd_trx_seqno(thd));
12629
11/20
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2106 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
2107 WSREP_DEBUG("%s", thd->wsrep_info);
12630 2107 thd_proc_info(thd, thd->wsrep_info);
12631 }
12632 #endif /* WITH_WSREP */
12633
12634 /* m_table->record[0] contains the BI */
12635 42486 m_table->mark_columns_per_binlog_row_image(thd);
12636 42486 error = m_table->file->ha_delete_row(m_table->record[0]);
12637 42486 m_table->default_column_bitmaps();
12638 42486 return error;
12639 }
12640
12641 #endif /* defined(MYSQL_SERVER) */
12642
12643 #ifndef MYSQL_SERVER
12644 4590 void Delete_rows_log_event::print(FILE *file,
12645 PRINT_EVENT_INFO *print_event_info) const {
12646 4590 Rows_log_event::print_helper(file, print_event_info);
12647 4590 }
12648 #endif
12649
12650 /**************************************************************************
12651 Update_rows_log_event member functions
12652 **************************************************************************/
12653
12654 #if defined(MYSQL_SERVER)
12655 683824 binary_log::Log_event_type Update_rows_log_event::get_update_rows_event_type(
12656 const THD *thd_arg) {
12657
1/2
✓ Branch 0 taken 683826 times.
✗ Branch 1 not taken.
683824 DBUG_TRACE;
12658 683826 binary_log::Log_event_type type =
12659 683826 (thd_arg->variables.binlog_row_value_options != 0
12660
2/2
✓ Branch 0 taken 674436 times.
✓ Branch 1 taken 9390 times.
1358262 ? binary_log::PARTIAL_UPDATE_ROWS_EVENT
12661
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 674430 times.
674436 : (log_bin_use_v1_row_events ? binary_log::UPDATE_ROWS_EVENT_V1
12662 : binary_log::UPDATE_ROWS_EVENT));
12663
3/10
✓ Branch 0 taken 683825 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 683826 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 683826 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
683826 DBUG_PRINT("info", ("update_rows event_type: %s", get_type_str(type)));
12664 683826 return type;
12665 683826 }
12666
12667 /*
12668 Constructor used to build an event for writing to the binary log.
12669 */
12670 455884 Update_rows_log_event::Update_rows_log_event(
12671 THD *thd_arg, TABLE *tbl_arg, const Table_id &tid, bool is_transactional,
12672 455884 const unsigned char *extra_row_ndb_info)
12673 : binary_log::Rows_event(get_update_rows_event_type(thd_arg)),
12674 455884 Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
12675 get_update_rows_event_type(thd_arg), extra_row_ndb_info),
12676
4/8
✓ Branch 0 taken 227942 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 227940 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 227939 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 227939 times.
✗ Branch 7 not taken.
455884 binary_log::Update_rows_event(get_update_rows_event_type(thd_arg)) {
12677
1/2
✓ Branch 0 taken 227942 times.
✗ Branch 1 not taken.
455878 DBUG_TRACE;
12678
3/10
✓ Branch 0 taken 227941 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 227942 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 227942 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
455884 DBUG_PRINT("info", ("update_rows event_type: %s", get_type_str()));
12679 455884 common_header->type_code = m_type;
12680
1/2
✓ Branch 0 taken 227942 times.
✗ Branch 1 not taken.
455884 init(tbl_arg->write_set);
12681
2/6
✓ Branch 0 taken 227938 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 227938 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
455884 common_header->set_is_valid(Rows_log_event::is_valid() && m_cols_ai.bitmap);
12682 }
12683
12684 3815524 bool Update_rows_log_event::binlog_row_logging_function(
12685 THD *thd_arg, TABLE *table, bool is_transactional,
12686 const uchar *before_record, const uchar *after_record) {
12687 3815524 return thd_arg->binlog_update_row(table, is_transactional, before_record,
12688 3815525 after_record, nullptr);
12689 }
12690
12691 227939 void Update_rows_log_event::init(MY_BITMAP const *cols) {
12692 /* if bitmap_init fails, caught in is_valid() */
12693
1/2
✓ Branch 0 taken 227942 times.
✗ Branch 1 not taken.
227939 if (likely(!bitmap_init(
12694 &m_cols_ai,
12695 227939 m_width <= sizeof(m_bitbuf_ai) * 8 ? m_bitbuf_ai : nullptr,
12696
2/2
✓ Branch 0 taken 227921 times.
✓ Branch 1 taken 18 times.
227939 m_width))) {
12697 /* Cols can be zero if this is a dummy binrows event */
12698
1/2
✓ Branch 0 taken 227942 times.
✗ Branch 1 not taken.
227942 if (likely(cols != nullptr)) {
12699 // 'cols' may have additional hidden columns at the end.
12700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 227942 times.
227942 assert(cols->n_bits >= m_cols_ai.n_bits);
12701 227942 bitmap_n_copy(&m_cols_ai, cols);
12702 }
12703 }
12704 227941 }
12705 #endif /* defined(MYSQL_SERVER) */
12706
12707 1845948 Update_rows_log_event::~Update_rows_log_event() {
12708
1/2
✓ Branch 0 taken 461488 times.
✗ Branch 1 not taken.
922974 if (m_cols_ai.bitmap) {
12709
2/2
✓ Branch 0 taken 461462 times.
✓ Branch 1 taken 26 times.
922976 if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
12710 922924 m_cols_ai.bitmap = nullptr; // so no my_free in bitmap_free
12711 922976 bitmap_free(&m_cols_ai); // To pair with bitmap_init().
12712 }
12713 }
12714
12715 /*
12716 Constructor used by slave to read the event from the binary log.
12717 */
12718 467106 Update_rows_log_event::Update_rows_log_event(
12719 467106 const char *buf, const Format_description_event *description_event)
12720 : binary_log::Rows_event(buf, description_event),
12721 Rows_log_event(buf, description_event),
12722
2/4
✓ Branch 0 taken 233553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 233553 times.
✗ Branch 3 not taken.
467106 binary_log::Update_rows_event(buf, description_event) {
12723
1/2
✓ Branch 0 taken 233553 times.
✗ Branch 1 not taken.
467106 DBUG_TRACE;
12724
3/4
✓ Branch 0 taken 223504 times.
✓ Branch 1 taken 10049 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 223504 times.
467106 if (!is_valid()) return;
12725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 233553 times.
467106 assert(header()->type_code == m_type);
12726 467106 common_header->set_is_valid(m_cols_ai.bitmap);
12727 }
12728
12729 #if defined(MYSQL_SERVER)
12730
12731 25983 int Update_rows_log_event::do_before_row_operations(
12732 const Slave_reporting_capability *const) {
12733 25983 int error = 0;
12734
1/2
✓ Branch 0 taken 25983 times.
✗ Branch 1 not taken.
25983 DBUG_TRACE;
12735
1/2
✓ Branch 0 taken 25983 times.
✗ Branch 1 not taken.
25983 m_table->file->rpl_before_update_rows();
12736 /*
12737 Increment the global status update count variable
12738 */
12739
2/2
✓ Branch 0 taken 24168 times.
✓ Branch 1 taken 1815 times.
25983 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_UPDATE]++;
12740
12741 /*
12742 Let storage engines treat this event as an UPDATE command.
12743
12744 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
12745 When locking the tables, it should be SQLCOM_END.
12746 THD::decide_logging_format which is called from "lock tables"
12747 assumes that row_events will have 'sql_command' as SQLCOM_END.
12748 */
12749 25983 thd->lex->sql_command = SQLCOM_UPDATE;
12750
12751
1/2
✓ Branch 0 taken 25983 times.
✗ Branch 1 not taken.
25983 error = row_operations_scan_and_key_setup();
12752 25983 return error;
12753 25983 }
12754
12755 25980 int Update_rows_log_event::do_after_row_operations(
12756 const Slave_reporting_capability *const, int error) {
12757
1/2
✓ Branch 0 taken 25980 times.
✗ Branch 1 not taken.
25980 DBUG_TRACE;
12758
1/2
✓ Branch 0 taken 25980 times.
✗ Branch 1 not taken.
25980 error = row_operations_scan_and_key_teardown(error);
12759
1/2
✓ Branch 0 taken 25980 times.
✗ Branch 1 not taken.
25980 m_table->file->rpl_after_update_rows();
12760 25980 return error;
12761 25980 }
12762
12763 610250 int Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) {
12764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 610250 times.
610250 assert(m_table != nullptr);
12765 610250 int error = 0;
12766
12767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 610250 times.
610250 if (m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED) {
12768 error = unpack_current_row(rli, &m_cols, false, false);
12769 if (error) return error;
12770 }
12771
12772 /*
12773 This is the situation after locating BI:
12774
12775 ===|=== before image ====|=== after image ===|===
12776 ^ ^
12777 m_curr_row m_curr_row_end
12778
12779 BI found in the table is stored in record[0]. We copy it to record[1]
12780 and unpack AI to record[0].
12781 */
12782
12783 610250 store_record(m_table, record[1]);
12784
12785 610250 m_curr_row = m_curr_row_end;
12786 /* this also updates m_curr_row_end */
12787
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 610133 times.
610250 if ((error = unpack_current_row(rli, &m_cols_ai, true /*is AI*/)))
12788 117 return error;
12789
12790 // Invoke check constraints on the unpacked row.
12791
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 610132 times.
610133 if (invoke_table_check_constraints(thd, m_table))
12792 1 return ER_CHECK_CONSTRAINT_VIOLATED;
12793
12794 /*
12795 Now we have the right row to update. The old row (the one we're
12796 looking for) is in record[1] and the new row is in record[0].
12797 */
12798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 610132 times.
610132 DBUG_PRINT("info", ("Updating row in table"));
12799 610132 DBUG_DUMP("old record", m_table->record[1], m_table->s->reclength);
12800 610132 DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength);
12801
12802 #ifdef WITH_WSREP
12803
5/8
✓ Branch 0 taken 610132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 403948 times.
✓ Branch 3 taken 206184 times.
✓ Branch 4 taken 403948 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 403948 times.
✗ Branch 7 not taken.
610132 if (WSREP(thd)) {
12804 403948 THD_STAGE_INFO(thd, stage_wsrep_updating_rows);
12805 807896 snprintf(thd->wsrep_info, sizeof(thd->wsrep_info),
12806 "wsrep: updating row for write-set (%lld)",
12807 403948 (long long)wsrep_thd_trx_seqno(thd));
12808
11/20
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 403941 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 7 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 7 times.
403948 WSREP_DEBUG("%s", thd->wsrep_info);
12809 403948 thd_proc_info(thd, thd->wsrep_info);
12810 }
12811 #endif /* WITH_WSREP */
12812
12813 610132 m_table->mark_columns_per_binlog_row_image(thd);
12814 610132 error = m_table->file->ha_update_row(m_table->record[1], m_table->record[0]);
12815
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 610127 times.
610129 if (error == HA_ERR_RECORD_IS_THE_SAME) error = 0;
12816 610129 m_table->default_column_bitmaps();
12817
12818 610129 return error;
12819 }
12820
12821 #endif /* defined(MYSQL_SERVER) */
12822
12823 #ifndef MYSQL_SERVER
12824 6968 void Update_rows_log_event::print(FILE *file,
12825 PRINT_EVENT_INFO *print_event_info) const {
12826 6968 Rows_log_event::print_helper(file, print_event_info);
12827 6968 }
12828 #endif
12829
12830 25 Incident_log_event::Incident_log_event(
12831 25 const char *buf, const Format_description_event *description_event)
12832 : binary_log::Incident_event(buf, description_event),
12833
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
25 Log_event(header(), footer()) {
12834
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 DBUG_TRACE;
12835 25 }
12836
12837 122 Incident_log_event::~Incident_log_event() {
12838
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 3 times.
72 if (message) bapi_free(message);
12839 122 }
12840
12841 15 const char *Incident_log_event::description() const {
12842 static const char *const description[] = {"NOTHING", // Not used
12843 "LOST_EVENTS"};
12844
12845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 DBUG_PRINT("info", ("incident: %d", incident));
12846
12847 15 return description[incident];
12848 }
12849
12850 #ifdef MYSQL_SERVER
12851 9 int Incident_log_event::pack_info(Protocol *protocol) {
12852 char buf[256];
12853 size_t bytes;
12854
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (message_length > 0)
12855
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 bytes = snprintf(buf, sizeof(buf), "#%d (%s)", incident, description());
12856 else
12857 bytes = snprintf(buf, sizeof(buf), "#%d (%s): %s", incident, description(),
12858 message);
12859
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 protocol->store_string(buf, bytes, &my_charset_bin);
12860 9 return 0;
12861 }
12862 #endif
12863
12864 #ifndef MYSQL_SERVER
12865 1 void Incident_log_event::print(FILE *,
12866 PRINT_EVENT_INFO *print_event_info) const {
12867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (print_event_info->short_form) return;
12868
12869 1 print_header(&print_event_info->head_cache, print_event_info, false);
12870 1 my_b_printf(
12871 &print_event_info->head_cache,
12872 "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n",
12873 description());
12874 }
12875 #endif
12876
12877 #if defined(MYSQL_SERVER)
12878 8 int Incident_log_event::do_apply_event(Relay_log_info const *rli) {
12879
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 DBUG_TRACE;
12880
12881 /*
12882 It is not necessary to do GTID related check if the error
12883 'ER_SLAVE_INCIDENT' is ignored.
12884 */
12885
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
8 if (ignored_error_code(ER_SLAVE_INCIDENT)) {
12886
3/8
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
2 DBUG_PRINT("info", ("Ignoring Incident"));
12887
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 mysql_bin_log.gtid_end_transaction(thd);
12888 2 return 0;
12889 }
12890
12891
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
12892
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if (state == GTID_STATEMENT_EXECUTE) {
12893
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (gtid_pre_statement_post_implicit_commit_checks(thd))
12894 state = GTID_STATEMENT_CANCEL;
12895 }
12896
12897
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (state == GTID_STATEMENT_CANCEL) {
12898 uint error = thd->get_stmt_da()->mysql_errno();
12899 assert(error != 0);
12900 rli->report(ERROR_LEVEL, error, "Error executing incident event: '%s'",
12901 thd->get_stmt_da()->message_text());
12902 thd->is_slave_error = true;
12903 return -1;
12904
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 } else if (state == GTID_STATEMENT_SKIP) {
12905 /*
12906 Make slave skip the Incident event through general commands of GTID
12907 i.e. 'set gtid_next=<GTID>; begin; commit;'.
12908 */
12909 1 return 0;
12910 }
12911
12912
3/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 rli->report(ERROR_LEVEL, ER_SLAVE_INCIDENT, ER_THD(thd, ER_SLAVE_INCIDENT),
12913
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 description(), message_length > 0 ? message : "<none>");
12914 5 return 1;
12915 8 }
12916
12917 10 bool Incident_log_event::write_data_header(Basic_ostream *ostream) {
12918
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 DBUG_TRACE;
12919
3/8
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
10 DBUG_PRINT("enter", ("incident: %d", incident));
12920 uchar buf[sizeof(int16)];
12921 10 int2store(buf, (int16)incident);
12922
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
20 return wrapper_my_b_safe_write(ostream, buf, sizeof(buf));
12923 10 }
12924
12925 /*
12926 Stores string to an output stream.
12927
12928 Writes str to file in the following format:
12929 1. Stores length using only one byte (255 maximum value);
12930 2. Stores complete str.
12931 */
12932
12933 85 static bool write_str_at_most_255_bytes(Basic_ostream *ostream, const char *str,
12934 uint length) {
12935 uchar tmp[1];
12936
12937 85 tmp[0] = (uchar)length;
12938 return (
12939
3/6
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 85 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 85 times.
✗ Branch 5 not taken.
170 ostream->write(tmp, sizeof(tmp)) ||
12940
2/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 85 times.
170 (length > 0 && ostream->write(pointer_cast<const uchar *>(str), length)));
12941 }
12942
12943 10 bool Incident_log_event::write_data_body(Basic_ostream *ostream) {
12944 uchar tmp[1];
12945
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 DBUG_TRACE;
12946 10 tmp[0] = (uchar)message_length;
12947
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 crc = checksum_crc32(crc, (uchar *)tmp, 1);
12948
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (message_length > 0) {
12949
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 crc = checksum_crc32(crc, (uchar *)message, message_length);
12950 // todo: report a bug on write_str accepts uint but treats it as uchar
12951 }
12952
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
20 return write_str_at_most_255_bytes(ostream, message, (uint)message_length);
12953 10 }
12954 #endif
12955
12956 256 Ignorable_log_event::Ignorable_log_event(
12957 2 const char *buf, const Format_description_event *descr_event)
12958 : binary_log::Ignorable_event(buf, descr_event),
12959
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
256 Log_event(header(), footer()) {
12960
1/2
✓ Branch 0 taken 128 times.
✗ Branch 1 not taken.
256 DBUG_TRACE;
12961 256 }
12962
12963 408 Ignorable_log_event::~Ignorable_log_event() = default;
12964
12965 #ifdef MYSQL_SERVER
12966 /* Pack info for its unrecognized ignorable event */
12967 int Ignorable_log_event::pack_info(Protocol *protocol) {
12968 char buf[256];
12969 size_t bytes;
12970 bytes = snprintf(buf, sizeof(buf), "# Unrecognized ignorable event");
12971 protocol->store_string(buf, bytes, &my_charset_bin);
12972 return 0;
12973 }
12974 #endif
12975
12976 #ifndef MYSQL_SERVER
12977 /* Print for its unrecognized ignorable event */
12978 void Ignorable_log_event::print(FILE *,
12979 PRINT_EVENT_INFO *print_event_info) const {
12980 if (print_event_info->short_form) return;
12981
12982 print_header(&print_event_info->head_cache, print_event_info, false);
12983 my_b_printf(&print_event_info->head_cache, "\tIgnorable\n");
12984 my_b_printf(&print_event_info->head_cache,
12985 "# Unrecognized ignorable event\n");
12986 }
12987 #endif
12988
12989 254 Rows_query_log_event::Rows_query_log_event(
12990 254 const char *buf, const Format_description_event *descr_event)
12991 : binary_log::Ignorable_event(buf, descr_event),
12992 Ignorable_log_event(buf, descr_event),
12993
2/4
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 127 times.
✗ Branch 3 not taken.
254 binary_log::Rows_query_event(buf, descr_event) {
12994
1/2
✓ Branch 0 taken 127 times.
✗ Branch 1 not taken.
254 DBUG_TRACE;
12995 }
12996
12997 #ifdef MYSQL_SERVER
12998 46 int Rows_query_log_event::pack_info(Protocol *protocol) {
12999 char *buf;
13000 size_t bytes;
13001 46 size_t len = sizeof("# ") + strlen(m_rows_query);
13002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (!(buf = (char *)my_malloc(key_memory_log_event, len, MYF(MY_WME))))
13003 return 1;
13004 46 bytes = snprintf(buf, len, "# %s", m_rows_query);
13005 46 protocol->store_string(buf, bytes, &my_charset_bin);
13006 46 my_free(buf);
13007 46 return 0;
13008 }
13009 #endif
13010
13011 #ifndef MYSQL_SERVER
13012 28 void Rows_query_log_event::print(FILE *,
13013 PRINT_EVENT_INFO *print_event_info) const {
13014
3/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 1 times.
28 if (!print_event_info->short_form && print_event_info->verbose > 1) {
13015 27 IO_CACHE *const head = &print_event_info->head_cache;
13016 27 IO_CACHE *const body = &print_event_info->body_cache;
13017 27 char *token = nullptr, *saveptr = nullptr;
13018 27 char *rows_query_copy = nullptr;
13019 27 if (!(rows_query_copy =
13020
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 my_strdup(key_memory_log_event, m_rows_query, MYF(MY_WME))))
13021 return;
13022
13023
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 print_header(head, print_event_info, false);
13024
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 my_b_printf(head, "\tRows_query\n");
13025 /*
13026 Prefix every line of a multi-line query with '#' to prevent the
13027 statement from being executed when binary log will be processed
13028 using 'mysqlbinlog --verbose --verbose'.
13029 */
13030
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 27 times.
56 for (token = my_strtok_r(rows_query_copy, "\n", &saveptr); token;
13031 29 token = my_strtok_r(nullptr, "\n", &saveptr))
13032
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 my_b_printf(head, "# %s\n", token);
13033
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 my_free(rows_query_copy);
13034
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
27 print_base64(body, print_event_info, true);
13035 }
13036 }
13037 #endif
13038
13039 #if defined(MYSQL_SERVER)
13040 75 bool Rows_query_log_event::write_data_body(Basic_ostream *ostream) {
13041
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
75 DBUG_TRACE;
13042 /*
13043 m_rows_query length will be stored using only one byte, but on read
13044 that length will be ignored and the complete query will be read.
13045 */
13046 150 return write_str_at_most_255_bytes(ostream, m_rows_query,
13047
1/2
✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
150 strlen(m_rows_query));
13048 75 }
13049
13050 52 int Rows_query_log_event::do_apply_event(Relay_log_info const *rli) {
13051
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 DBUG_TRACE;
13052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 assert(rli->info_thd == thd);
13053 /* Set query for writing Rows_query log event into binlog later.*/
13054
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 thd->set_query(m_rows_query, strlen(m_rows_query));
13055
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 thd->set_query_for_display(m_rows_query, strlen(m_rows_query));
13056
13057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 assert(rli->rows_query_ev == nullptr);
13058
13059 52 const_cast<Relay_log_info *>(rli)->rows_query_ev = this;
13060 /* Tell worker not to free the event */
13061 52 worker = nullptr;
13062
13063
3/4
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 49 times.
52 DBUG_EXECUTE_IF("error_on_rows_query_event_apply", { return 1; };);
13064 49 return 0;
13065 52 }
13066 #endif
13067
13068 const char *Gtid_log_event::SET_STRING_PREFIX = "SET @@SESSION.GTID_NEXT= '";
13069
13070 1826240 Gtid_log_event::Gtid_log_event(
13071 1826240 const char *buffer, const Format_description_event *description_event)
13072 : binary_log::Gtid_event(buffer, description_event),
13073
1/2
✓ Branch 0 taken 1785180 times.
✗ Branch 1 not taken.
1826240 Log_event(header(), footer()) {
13074
1/2
✓ Branch 0 taken 1826258 times.
✗ Branch 1 not taken.
1826255 DBUG_TRACE;
13075
3/4
✓ Branch 0 taken 1785180 times.
✓ Branch 1 taken 41075 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1785180 times.
1826258 if (!is_valid()) return;
13076
13077 #ifndef NDEBUG
13078 1826255 uint8_t const common_header_len = description_event->common_header_len;
13079 uint8 const post_header_len =
13080 1826255 buffer[EVENT_TYPE_OFFSET] == binary_log::ANONYMOUS_GTID_LOG_EVENT
13081
2/2
✓ Branch 0 taken 1577545 times.
✓ Branch 1 taken 248710 times.
3652510 ? description_event
13082 1577545 ->post_header_len[binary_log::ANONYMOUS_GTID_LOG_EVENT - 1]
13083 248710 : description_event->post_header_len[binary_log::GTID_LOG_EVENT - 1];
13084
3/8
✓ Branch 0 taken 1826256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1826250 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1826250 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1826255 DBUG_PRINT("info",
13085 ("event_len: %zu; common_header_len: %d; post_header_len: %d",
13086 header()->data_written, common_header_len, post_header_len));
13087 #endif
13088
13089 1826250 spec.type = get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT
13090
2/2
✓ Branch 0 taken 1577545 times.
✓ Branch 1 taken 248703 times.
1826248 ? ANONYMOUS_GTID
13091 : ASSIGNED_GTID;
13092 1826248 sid.copy_from((uchar *)Uuid_parent_struct.bytes);
13093 1826249 spec.gtid.sidno = gtid_info_struct.rpl_gtid_sidno;
13094 1826249 spec.gtid.gno = gtid_info_struct.rpl_gtid_gno;
13095
1/2
✓ Branch 0 taken 1826255 times.
✗ Branch 1 not taken.
1826249 }
13096
13097 #ifdef MYSQL_SERVER
13098 2590142 Gtid_log_event::Gtid_log_event(THD *thd_arg, bool using_trans,
13099 int64 last_committed_arg,
13100 int64 sequence_number_arg,
13101 bool may_have_sbr_stmts_arg,
13102 ulonglong original_commit_timestamp_arg,
13103 ulonglong immediate_commit_timestamp_arg,
13104 uint32_t original_server_version_arg,
13105 2590142 uint32_t immediate_server_version_arg)
13106 : binary_log::Gtid_event(
13107 last_committed_arg, sequence_number_arg, may_have_sbr_stmts_arg,
13108 original_commit_timestamp_arg, immediate_commit_timestamp_arg,
13109 original_server_version_arg, immediate_server_version_arg),
13110 Log_event(thd_arg,
13111 2590142 thd_arg->variables.gtid_next.type == ANONYMOUS_GTID
13112 ? LOG_EVENT_IGNORABLE_F
13113 : 0,
13114 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
13115 : Log_event::EVENT_STMT_CACHE,
13116
5/6
✓ Branch 0 taken 2099954 times.
✓ Branch 1 taken 490188 times.
✓ Branch 2 taken 224984 times.
✓ Branch 3 taken 2365158 times.
✓ Branch 4 taken 2590142 times.
✗ Branch 5 not taken.
2590142 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
13117
1/2
✓ Branch 0 taken 2590142 times.
✗ Branch 1 not taken.
2590142 DBUG_TRACE;
13118
2/2
✓ Branch 0 taken 123932 times.
✓ Branch 1 taken 2466210 times.
2590142 if (thd->owned_gtid.sidno > 0) {
13119 123932 spec.set(thd->owned_gtid);
13120 123932 sid = thd->owned_sid;
13121 } else {
13122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2466210 times.
2466210 assert(thd->owned_gtid.sidno == THD::OWNED_SIDNO_ANONYMOUS);
13123 2466210 spec.set_anonymous();
13124 2466210 spec.gtid.clear();
13125 2466210 sid.clear();
13126 }
13127
13128 2590142 Log_event_type event_type =
13129
2/2
✓ Branch 0 taken 2466210 times.
✓ Branch 1 taken 123932 times.
2590142 (spec.type == ANONYMOUS_GTID ? binary_log::ANONYMOUS_GTID_LOG_EVENT
13130 : binary_log::GTID_LOG_EVENT);
13131 2590142 common_header->type_code = event_type;
13132
13133 #ifndef NDEBUG
13134 char buf[MAX_SET_STRING_LENGTH + 1];
13135
1/2
✓ Branch 0 taken 2590142 times.
✗ Branch 1 not taken.
2590142 to_string(buf);
13136
5/8
✓ Branch 0 taken 2590142 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2590142 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 114 times.
✓ Branch 5 taken 2590028 times.
✓ Branch 6 taken 114 times.
✗ Branch 7 not taken.
2590142 DBUG_PRINT("info", ("%s", buf));
13137 #endif
13138 2590142 common_header->set_is_valid(true);
13139 2590142 }
13140
13141 30836 Gtid_log_event::Gtid_log_event(
13142 uint32 server_id_arg, bool using_trans, int64 last_committed_arg,
13143 int64 sequence_number_arg, bool may_have_sbr_stmts_arg,
13144 ulonglong original_commit_timestamp_arg,
13145 ulonglong immediate_commit_timestamp_arg, const Gtid_specification spec_arg,
13146 30836 uint32_t original_server_version_arg, uint32_t immediate_server_version_arg)
13147 : binary_log::Gtid_event(
13148 last_committed_arg, sequence_number_arg, may_have_sbr_stmts_arg,
13149 original_commit_timestamp_arg, immediate_commit_timestamp_arg,
13150 original_server_version_arg, immediate_server_version_arg),
13151 Log_event(header(), footer(),
13152 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
13153 : Log_event::EVENT_STMT_CACHE,
13154
3/4
✓ Branch 0 taken 17040 times.
✓ Branch 1 taken 13796 times.
✓ Branch 2 taken 30836 times.
✗ Branch 3 not taken.
30836 Log_event::EVENT_NORMAL_LOGGING) {
13155
1/2
✓ Branch 0 taken 30836 times.
✗ Branch 1 not taken.
30836 DBUG_TRACE;
13156 30836 server_id = server_id_arg;
13157 30836 common_header->unmasked_server_id = server_id_arg;
13158 30836 common_header->set_is_valid(true);
13159
13160
2/2
✓ Branch 0 taken 30835 times.
✓ Branch 1 taken 1 times.
30836 if (spec_arg.type == ASSIGNED_GTID) {
13161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30835 times.
30835 assert(spec_arg.gtid.sidno > 0);
13162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30835 times.
30835 assert(spec_arg.gtid.gno > 0);
13163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30835 times.
30835 assert(spec_arg.gtid.gno < GNO_END);
13164
2/4
✓ Branch 0 taken 30835 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30835 times.
30835 if (spec_arg.gtid.gno <= 0 || spec_arg.gtid.gno >= GNO_END)
13165 common_header->set_is_valid(false);
13166 30835 spec.set(spec_arg.gtid);
13167
1/2
✓ Branch 0 taken 30835 times.
✗ Branch 1 not taken.
30835 global_sid_lock->rdlock();
13168
1/2
✓ Branch 0 taken 30835 times.
✗ Branch 1 not taken.
30835 sid = global_sid_map->sidno_to_sid(spec_arg.gtid.sidno);
13169
1/2
✓ Branch 0 taken 30835 times.
✗ Branch 1 not taken.
30835 global_sid_lock->unlock();
13170 } else {
13171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(spec_arg.type == ANONYMOUS_GTID);
13172 1 spec.set_anonymous();
13173 1 spec.gtid.clear();
13174 1 sid.clear();
13175 1 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13176 }
13177
13178 30836 Log_event_type event_type =
13179
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30835 times.
30836 (spec.type == ANONYMOUS_GTID ? binary_log::ANONYMOUS_GTID_LOG_EVENT
13180 : binary_log::GTID_LOG_EVENT);
13181 30836 common_header->type_code = event_type;
13182
13183 #ifndef NDEBUG
13184 char buf[MAX_SET_STRING_LENGTH + 1];
13185
1/2
✓ Branch 0 taken 30836 times.
✗ Branch 1 not taken.
30836 to_string(buf);
13186
5/8
✓ Branch 0 taken 30836 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30836 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 30834 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
30836 DBUG_PRINT("info", ("%s", buf));
13187 #endif
13188 30836 }
13189
13190 23353 int Gtid_log_event::pack_info(Protocol *protocol) {
13191 char buffer[MAX_SET_STRING_LENGTH + 1];
13192
1/2
✓ Branch 0 taken 23353 times.
✗ Branch 1 not taken.
23353 size_t len = to_string(buffer);
13193
1/2
✓ Branch 0 taken 23353 times.
✗ Branch 1 not taken.
23353 protocol->store_string(buffer, len, &my_charset_bin);
13194 23353 return 0;
13195 }
13196 #endif // MYSQL_SERVER
13197
13198 2678266 size_t Gtid_log_event::to_string(char *buf) const {
13199 2678266 char *p = buf;
13200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2678266 times.
2678266 assert(strlen(SET_STRING_PREFIX) == SET_STRING_PREFIX_LENGTH);
13201 2678266 strcpy(p, SET_STRING_PREFIX);
13202 2678266 p += SET_STRING_PREFIX_LENGTH;
13203 2678266 p += spec.to_string(&sid, p);
13204 2678266 *p++ = '\'';
13205 2678266 *p = '\0';
13206 2678266 return p - buf;
13207 }
13208
13209 #ifndef MYSQL_SERVER
13210 33935 void Gtid_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
13211 char buffer[MAX_SET_STRING_LENGTH + 1];
13212 33935 IO_CACHE *const head = &print_event_info->head_cache;
13213
2/2
✓ Branch 0 taken 33080 times.
✓ Branch 1 taken 855 times.
33935 if (!print_event_info->short_form) {
13214
1/2
✓ Branch 0 taken 33080 times.
✗ Branch 1 not taken.
33080 print_header(head, print_event_info, false);
13215
3/4
✓ Branch 0 taken 19473 times.
✓ Branch 1 taken 13607 times.
✓ Branch 2 taken 33080 times.
✗ Branch 3 not taken.
66160 my_b_printf(head,
13216 "\t%s\tlast_committed=%llu\tsequence_number=%llu\t"
13217 "rbr_only=%s\t"
13218 "original_committed_timestamp=%llu\t"
13219 "immediate_commit_timestamp=%llu\t"
13220 "transaction_length=%llu\n",
13221 33080 get_type_code() == binary_log::GTID_LOG_EVENT
13222 ? "GTID"
13223 : "Anonymous_GTID",
13224 33080 last_committed, sequence_number,
13225 33080 may_have_sbr_stmts ? "no" : "yes", original_commit_timestamp,
13226
2/2
✓ Branch 0 taken 20015 times.
✓ Branch 1 taken 13065 times.
33080 immediate_commit_timestamp, transaction_length);
13227 }
13228
13229 /*
13230 The applier thread can always use "READ COMMITTED" isolation for
13231 transactions containing only RBR events (Table_map + Rows).
13232
13233 This would prevent some deadlock issues because InnoDB doesn't
13234 acquire GAP locks in "READ COMMITTED" isolation level since
13235 MySQL 5.7.18.
13236 */
13237
2/2
✓ Branch 0 taken 13067 times.
✓ Branch 1 taken 20868 times.
33935 if (!may_have_sbr_stmts) {
13238 13067 my_b_printf(head,
13239 "/*!50718 SET TRANSACTION ISOLATION LEVEL "
13240 "READ COMMITTED*/%s\n",
13241
1/2
✓ Branch 0 taken 13067 times.
✗ Branch 1 not taken.
13067 print_event_info->delimiter);
13242 }
13243
13244 /*
13245 We always print the original commit timestamp in order to make
13246 dumps from binary logs generated on servers without this info on
13247 GTID events to print "0" (not known) as the session value.
13248 */
13249 char llbuf[22];
13250
13251 char immediate_commit_timestamp_str[256];
13252 char original_commit_timestamp_str[256];
13253
13254 33935 microsecond_timestamp_to_str(immediate_commit_timestamp,
13255 immediate_commit_timestamp_str);
13256 33935 microsecond_timestamp_to_str(original_commit_timestamp,
13257 original_commit_timestamp_str);
13258
13259
1/2
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
33935 my_b_printf(head, "# original_commit_timestamp=%s (%s)\n",
13260
1/2
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
33935 llstr(original_commit_timestamp, llbuf),
13261 original_commit_timestamp_str);
13262
1/2
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
33935 my_b_printf(head, "# immediate_commit_timestamp=%s (%s)\n",
13263
1/2
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
33935 llstr(immediate_commit_timestamp, llbuf),
13264 immediate_commit_timestamp_str);
13265
13266
3/4
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33929 times.
✓ Branch 3 taken 6 times.
33935 if (DBUG_EVALUATE_IF("do_not_write_rpl_OCT", false, true)) {
13267
1/2
✓ Branch 0 taken 33929 times.
✗ Branch 1 not taken.
33929 my_b_printf(
13268 head, "/*!80001 SET @@session.original_commit_timestamp=%s*/%s\n",
13269
1/2
✓ Branch 0 taken 33929 times.
✗ Branch 1 not taken.
33929 llstr(original_commit_timestamp, llbuf), print_event_info->delimiter);
13270 }
13271
13272 33935 my_b_printf(head, "/*!80014 SET @@session.original_server_version=%u*/%s\n",
13273
1/2
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
33935 original_server_version, print_event_info->delimiter);
13274
13275 33935 my_b_printf(head, "/*!80014 SET @@session.immediate_server_version=%u*/%s\n",
13276
1/2
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
33935 immediate_server_version, print_event_info->delimiter);
13277
13278
1/2
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
33935 to_string(buffer);
13279
1/2
✓ Branch 0 taken 33935 times.
✗ Branch 1 not taken.
33935 my_b_printf(head, "%s%s\n", buffer, print_event_info->delimiter);
13280 33935 }
13281 #endif
13282
13283 #ifdef MYSQL_SERVER
13284 2621000 uint32 Gtid_log_event::write_post_header_to_memory(uchar *buffer) {
13285
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
2621000 DBUG_TRACE;
13286 2621000 uchar *ptr_buffer = buffer;
13287
13288 /* Encode the GTID flags */
13289 2621000 uchar gtid_flags = 0;
13290 1945562 gtid_flags |=
13291
2/2
✓ Branch 0 taken 675438 times.
✓ Branch 1 taken 1945562 times.
2621000 may_have_sbr_stmts ? binary_log::Gtid_event::FLAG_MAY_HAVE_SBR : 0;
13292 2621000 *ptr_buffer = gtid_flags;
13293 2621000 ptr_buffer += ENCODED_FLAG_LENGTH;
13294
13295 #ifndef NDEBUG
13296 char buf[binary_log::Uuid::TEXT_LENGTH + 1];
13297
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
2621000 sid.to_string(buf);
13298
5/8
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2621000 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 116 times.
✓ Branch 5 taken 2620884 times.
✓ Branch 6 taken 116 times.
✗ Branch 7 not taken.
2621000 DBUG_PRINT("info", ("sid=%s sidno=%d gno=%" PRId64, buf, spec.gtid.sidno,
13299 spec.gtid.gno));
13300 #endif
13301
13302 2621000 sid.copy_to(ptr_buffer);
13303 2621000 ptr_buffer += ENCODED_SID_LENGTH;
13304
13305 #ifndef NDEBUG
13306
2/4
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2621000 times.
2621000 if (DBUG_EVALUATE_IF("send_invalid_gno_to_replica", true, false))
13307 int8store(ptr_buffer, GNO_END);
13308 else
13309 #endif
13310 2621000 int8store(ptr_buffer, spec.gtid.gno);
13311 2621000 ptr_buffer += ENCODED_GNO_LENGTH;
13312
13313 2621000 *ptr_buffer = LOGICAL_TIMESTAMP_TYPECODE;
13314 2621000 ptr_buffer += LOGICAL_TIMESTAMP_TYPECODE_LENGTH;
13315
13316
4/6
✓ Branch 0 taken 3842 times.
✓ Branch 1 taken 2617158 times.
✓ Branch 2 taken 3842 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2617158 times.
2621000 assert((sequence_number == 0 && last_committed == 0) ||
13317 (sequence_number > last_committed));
13318
5/6
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3288 times.
✓ Branch 3 taken 2617712 times.
✓ Branch 4 taken 3260 times.
✓ Branch 5 taken 28 times.
2621000 DBUG_EXECUTE_IF("set_commit_parent_100", {
13319 last_committed =
13320 max<int64>(sequence_number > 1 ? 1 : 0, sequence_number - 100);
13321 });
13322
5/6
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 2620967 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 6 times.
2621000 DBUG_EXECUTE_IF("set_commit_parent_150", {
13323 last_committed =
13324 max<int64>(sequence_number > 1 ? 1 : 0, sequence_number - 150);
13325 });
13326
3/4
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2620999 times.
2621000 DBUG_EXECUTE_IF("feign_commit_parent", { last_committed = sequence_number; });
13327 2621000 int8store(ptr_buffer, last_committed);
13328 2621000 int8store(ptr_buffer + 8, sequence_number);
13329 2621000 ptr_buffer += LOGICAL_TIMESTAMP_LENGTH;
13330
13331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2621000 times.
2621000 assert(ptr_buffer == (buffer + POST_HEADER_LENGTH));
13332
13333 2621000 return POST_HEADER_LENGTH;
13334 2621000 }
13335
13336 #ifdef MYSQL_SERVER
13337 2621000 bool Gtid_log_event::write_data_header(Basic_ostream *ostream) {
13338
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
2621000 DBUG_TRACE;
13339 uchar buffer[POST_HEADER_LENGTH];
13340
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
2621000 write_post_header_to_memory(buffer);
13341
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
5242000 return wrapper_my_b_safe_write(ostream, (uchar *)buffer, POST_HEADER_LENGTH);
13342 2621000 }
13343
13344 2620999 uint32 Gtid_log_event::write_body_to_memory(uchar *buffer) {
13345
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
2620999 DBUG_TRACE;
13346
3/4
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2620998 times.
2621000 DBUG_EXECUTE_IF("do_not_write_rpl_timestamps", return 0;);
13347 2620998 uchar *ptr_buffer = buffer;
13348
13349 /*
13350 We want to modify immediate_commit_timestamp with the flag written
13351 in the highest bit(MSB). At the same time, we also want to have the original
13352 value to be able to use in if() later, so we use a temporary variable here.
13353 */
13354 2620998 ulonglong immediate_commit_timestamp_with_flag = immediate_commit_timestamp;
13355
13356 // Transaction did not originate at this server, set highest bit to hint this.
13357
2/2
✓ Branch 0 taken 294160 times.
✓ Branch 1 taken 2326838 times.
2620998 if (immediate_commit_timestamp != original_commit_timestamp)
13358 294160 immediate_commit_timestamp_with_flag |=
13359 (1ULL << ENCODED_COMMIT_TIMESTAMP_LENGTH);
13360 else // Clear highest bit(MSB)
13361 2326838 immediate_commit_timestamp_with_flag &=
13362 ~(1ULL << ENCODED_COMMIT_TIMESTAMP_LENGTH);
13363
13364 2620998 int7store(ptr_buffer, immediate_commit_timestamp_with_flag);
13365 2620998 ptr_buffer += IMMEDIATE_COMMIT_TIMESTAMP_LENGTH;
13366
13367
2/2
✓ Branch 0 taken 294160 times.
✓ Branch 1 taken 2326838 times.
2620998 if (immediate_commit_timestamp != original_commit_timestamp) {
13368 294160 int7store(ptr_buffer, original_commit_timestamp);
13369 294160 ptr_buffer += ORIGINAL_COMMIT_TIMESTAMP_LENGTH;
13370 }
13371
13372 // Write the transaction length information
13373
1/2
✓ Branch 0 taken 2620998 times.
✗ Branch 1 not taken.
2620998 uchar *ptr_after_length = net_store_length(ptr_buffer, transaction_length);
13374 2620998 ptr_buffer = ptr_after_length;
13375
13376 /*
13377 We want to modify immediate_server_version with the flag written to its MSB.
13378 At the same time, we also want to have the original value to be able to use
13379 it in if() later, so we use a temporary variable here.
13380 */
13381 2620998 uint32_t immediate_server_version_with_flag = immediate_server_version;
13382
13383
2/2
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 2620603 times.
2620998 if (immediate_server_version != original_server_version)
13384 395 immediate_server_version_with_flag |=
13385 (1ULL << ENCODED_SERVER_VERSION_LENGTH);
13386 else // Clear MSB
13387 2620603 immediate_server_version_with_flag &=
13388 ~(1ULL << ENCODED_SERVER_VERSION_LENGTH);
13389
13390 2620998 int4store(ptr_buffer, immediate_server_version_with_flag);
13391 2620998 ptr_buffer += IMMEDIATE_SERVER_VERSION_LENGTH;
13392
13393
2/2
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 2620603 times.
2620998 if (immediate_server_version != original_server_version) {
13394 395 int4store(ptr_buffer, original_server_version);
13395 395 ptr_buffer += ORIGINAL_SERVER_VERSION_LENGTH;
13396 }
13397
13398 2620998 return ptr_buffer - buffer;
13399 2621000 }
13400
13401 2620999 bool Gtid_log_event::write_data_body(Basic_ostream *ostream) {
13402
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
2620999 DBUG_TRACE;
13403 uchar buffer[MAX_DATA_LENGTH];
13404
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
2621000 uint32 len = write_body_to_memory(buffer);
13405
1/2
✓ Branch 0 taken 2621000 times.
✗ Branch 1 not taken.
5242000 return wrapper_my_b_safe_write(ostream, (uchar *)buffer, len);
13406 2621000 }
13407
13408 #endif // MYSQL_SERVER
13409
13410 #ifdef WITH_WSREP
13411
13412 /* Capture GTID event if PXC node is acting as ASYNC-SLAVE.
13413 This GTID event is appended as part of write-set creation in wsrep_replicate */
13414
13415 282742 static void wsrep_capture_gtid_event(THD *thd, Gtid_log_event *ev) {
13416 /* GTID events are also processed by applier but avoid capturing
13417 them then. GTID events are captured only as part of async slave
13418 replication. */
13419
6/6
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 282368 times.
✓ Branch 2 taken 372 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 341 times.
✓ Branch 5 taken 31 times.
282742 if (WSREP_ON && !thd->wsrep_applier) {
13420
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 259 times.
341 if (thd->wsrep_gtid_event_buf) {
13421
9/18
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 82 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 82 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 82 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 82 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 82 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 82 times.
82 WSREP_WARN(
13422 "Pending to replicate MySQL GTID event"
13423 " (probably a stale event). Discarding it now.");
13424 82 my_free((uchar *)thd->wsrep_gtid_event_buf);
13425 82 thd->wsrep_gtid_event_buf = NULL;
13426 82 thd->wsrep_gtid_event_buf_len = 0;
13427 }
13428
13429 341 ulong len = thd->wsrep_gtid_event_buf_len =
13430 341 uint4korr(ev->temp_buf + EVENT_LEN_OFFSET);
13431
13432 341 thd->wsrep_gtid_event_buf =
13433 341 (void *)my_realloc(key_memory_wsrep, thd->wsrep_gtid_event_buf,
13434 thd->wsrep_gtid_event_buf_len, MYF(0));
13435
13436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
341 if (!thd->wsrep_gtid_event_buf) {
13437 WSREP_WARN("GTID event allocation for slave failed");
13438 thd->wsrep_gtid_event_buf_len = 0;
13439 } else
13440 341 memcpy(thd->wsrep_gtid_event_buf, ev->temp_buf, len);
13441 }
13442 282742 }
13443
13444 #endif /* WITH_WSREP */
13445
13446 282745 int Gtid_log_event::do_apply_event(Relay_log_info const *rli) {
13447
1/2
✓ Branch 0 taken 282758 times.
✗ Branch 1 not taken.
282745 DBUG_TRACE;
13448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 282758 times.
282758 assert(rli->info_thd == thd);
13449
13450 /*
13451 In rare cases it is possible that we already own a GTID (either
13452 ANONYMOUS or ASSIGNED_GTID). This can happen if a transaction was truncated
13453 in the middle in the relay log and then next relay log begins with a
13454 Gtid_log_events without closing the transaction context from the previous
13455 relay log. In this case the only sensible thing to do is to discard the
13456 truncated transaction and move on.
13457
13458 Note that when the applier is "GTID skipping" a transactions it
13459 owns nothing, but its gtid_next->type == ASSIGNED_GTID.
13460 */
13461 282758 const Gtid_specification *gtid_next = &thd->variables.gtid_next;
13462
4/6
✓ Branch 0 taken 282755 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 282755 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 282746 times.
565516 if (!thd->owned_gtid_is_empty() ||
13463
4/6
✓ Branch 0 taken 282758 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 282758 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 282746 times.
282755 (thd->owned_gtid_is_empty() && gtid_next->type == ASSIGNED_GTID)) {
13464 /*
13465 Slave will execute this code if a previous Gtid_log_event was applied
13466 but the GTID wasn't consumed yet (the transaction was not committed,
13467 nor rolled back, nor skipped).
13468 On a client session we cannot do consecutive SET GTID_NEXT without
13469 a COMMIT or a ROLLBACK in the middle.
13470 Applying this event without rolling back the current transaction may
13471 lead to problems, as a "BEGIN" event following this GTID will
13472 implicitly commit the "partial transaction" and will consume the
13473 GTID. If this "partial transaction" was left in the relay log by the
13474 IO thread restarting in the middle of a transaction, you could have
13475 the partial transaction being logged with the GTID on the slave,
13476 causing data corruption on replication.
13477 */
13478
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (thd->server_status & SERVER_STATUS_IN_TRANS) {
13479 /* This is not an error (XA is safe), just an information */
13480 rli->report(INFORMATION_LEVEL, 0,
13481 "Rolling back unfinished transaction (no COMMIT "
13482 "or ROLLBACK in relay log). A probable cause is partial "
13483 "transaction left on relay log because of restarting IO "
13484 "thread with auto-positioning protocol.");
13485 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, true);
13486 }
13487
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 gtid_state->update_on_rollback(thd);
13488 }
13489
13490
1/2
✓ Branch 0 taken 282755 times.
✗ Branch 1 not taken.
282758 global_sid_lock->rdlock();
13491
13492 // make sure that sid has been converted to sidno
13493
2/2
✓ Branch 0 taken 59006 times.
✓ Branch 1 taken 223749 times.
282755 if (spec.type == ASSIGNED_GTID) {
13494
2/4
✓ Branch 0 taken 59007 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 59007 times.
59006 if (get_sidno(false) < 0) {
13495 global_sid_lock->unlock();
13496 return 1; // out of memory
13497 }
13498
4/4
✓ Branch 0 taken 223747 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 633 times.
✓ Branch 3 taken 223115 times.
447495 } else if ((spec.type == ANONYMOUS_GTID) &&
13499
3/4
✓ Branch 0 taken 223746 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 633 times.
✓ Branch 3 taken 223113 times.
223747 (rli->m_assign_gtids_to_anonymous_transactions_info.get_type() >
13500 Assign_gtids_to_anonymous_transactions_info::enum_type::
13501 AGAT_OFF)) {
13502
2/4
✓ Branch 0 taken 633 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 633 times.
633 assert(global_gtid_mode.get() == Gtid_mode::ON);
13503 633 spec.type = PRE_GENERATE_GTID;
13504 633 spec.gtid.sidno =
13505 633 rli->m_assign_gtids_to_anonymous_transactions_info.get_sidno();
13506 }
13507
13508 // set_gtid_next releases global_sid_lock
13509
3/4
✓ Branch 0 taken 282754 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 282752 times.
282755 if (set_gtid_next(thd, spec))
13510 // This can happen e.g. if gtid_mode is incompatible with spec.
13511 2 return 1;
13512
13513 /*
13514 Set the original_commit_timestamp.
13515 0 will be used if this event does not contain such information.
13516 */
13517
1/2
✓ Branch 0 taken 282749 times.
✗ Branch 1 not taken.
282752 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
13518 282749 thd->variables.original_commit_timestamp = original_commit_timestamp;
13519
1/2
✓ Branch 0 taken 282748 times.
✗ Branch 1 not taken.
282749 thd->set_original_commit_timestamp_for_slave_thread();
13520 /**
13521 Set the original/immediate server version.
13522 It will be set to UNKNOWN_SERVER_VERSION if the event does not contain such
13523 information.
13524 */
13525 282748 thd->variables.original_server_version = original_server_version;
13526 282748 thd->variables.immediate_server_version = immediate_server_version;
13527 282748 const_cast<Relay_log_info *>(rli)->started_processing(
13528
1/2
✓ Branch 0 taken 282754 times.
✗ Branch 1 not taken.
282748 thd->variables.gtid_next.gtid, original_commit_timestamp,
13529 immediate_commit_timestamp, state == GTID_STATEMENT_SKIP);
13530
13531 #ifdef WITH_WSREP
13532
1/2
✓ Branch 0 taken 282744 times.
✗ Branch 1 not taken.
282754 wsrep_capture_gtid_event(thd, this);
13533 #endif /* WITH_WSREP */
13534
13535 /*
13536 If the current transaction contains no changes logged with SBR
13537 we can assume this transaction as a pure row based replicated one.
13538
13539 Based on this assumption, we can set current transaction tx_isolation to
13540 READ COMMITTED in order to avoid concurrent transactions to be blocked by
13541 InnoDB gap locks.
13542
13543 The session tx_isolation will be restored:
13544 - When the transaction finishes with QUERY(COMMIT|ROLLBACK),
13545 as the MySQL server does for ordinary user sessions;
13546 - When applying a Xid_log_event, after committing the transaction;
13547 - When applying a XA_prepare_log_event, after preparing the transaction;
13548 - When the applier needs to abort a transaction execution.
13549
13550 Notice that when a transaction is being "gtid skipped", its statements are
13551 not actually executed (see mysql_execute_command()). So, the call to the
13552 function that would restore the tx_isolation after finishing the transaction
13553 may not happen.
13554 */
13555
11/14
✓ Branch 0 taken 282747 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 282747 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 130136 times.
✓ Branch 5 taken 152611 times.
✓ Branch 6 taken 130115 times.
✓ Branch 7 taken 21 times.
✓ Branch 8 taken 130117 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 128200 times.
✓ Branch 11 taken 1917 times.
✓ Branch 12 taken 128200 times.
✓ Branch 13 taken 154549 times.
282744 if (DBUG_EVALUATE_IF(
13556 "force_trx_as_rbr_only", true,
13557 !may_have_sbr_stmts && thd->tx_isolation > ISO_READ_COMMITTED &&
13558 gtid_pre_statement_checks(thd) != GTID_STATEMENT_SKIP)) {
13559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128200 times.
128200 assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT));
13560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128198 times.
128200 assert(thd->get_transaction()->is_empty(Transaction_ctx::SESSION));
13561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128198 times.
128198 assert(!thd->lock);
13562
3/8
✓ Branch 0 taken 128200 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 128197 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 128197 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
128198 DBUG_PRINT("info", ("setting tx_isolation to READ COMMITTED"));
13563
1/2
✓ Branch 0 taken 128189 times.
✗ Branch 1 not taken.
128197 set_tx_isolation(thd, ISO_READ_COMMITTED, true /*one_shot*/);
13564 }
13565
13566 282738 return 0;
13567 282740 }
13568
13569 1097 int Gtid_log_event::do_update_pos(Relay_log_info *rli) {
13570 /*
13571 This event does not increment group positions. This means
13572 that if there is a failure after it has been processed,
13573 it will be automatically re-executed.
13574 */
13575 1097 rli->inc_event_relay_log_pos();
13576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1097 times.
1097 DBUG_EXECUTE_IF(
13577 "crash_after_update_pos_gtid",
13578 sql_print_information("Crashing crash_after_update_pos_gtid.");
13579 DBUG_SUICIDE(););
13580 1097 return 0;
13581 }
13582
13583 282996 Log_event::enum_skip_reason Gtid_log_event::do_shall_skip(Relay_log_info *rli) {
13584 282996 return Log_event::continue_group(rli);
13585 }
13586 #endif // MYSQL_SERVER
13587
13588 2603399 void Gtid_log_event::set_trx_length_by_cache_size(ulonglong cache_size,
13589 bool is_checksum_enabled,
13590 int event_counter) {
13591 // Transaction content length
13592 2603399 transaction_length = cache_size;
13593
2/2
✓ Branch 0 taken 2589929 times.
✓ Branch 1 taken 13470 times.
2603399 if (is_checksum_enabled)
13594 2589929 transaction_length += event_counter * BINLOG_CHECKSUM_LEN;
13595
13596 // GTID length
13597 2603399 transaction_length += LOG_EVENT_HEADER_LEN;
13598 2603399 transaction_length += POST_HEADER_LENGTH;
13599 2603399 transaction_length += get_commit_timestamp_length();
13600 2603399 transaction_length += get_server_version_length();
13601
2/2
✓ Branch 0 taken 2589929 times.
✓ Branch 1 taken 13470 times.
2603399 transaction_length += is_checksum_enabled ? BINLOG_CHECKSUM_LEN : 0;
13602
13603 /*
13604 Notice that it is not possible to determine the transaction_length field
13605 size using pack.cc:net_length_size() since the length of the field itself
13606 must be added to the value.
13607
13608 Example: Suppose transaction_length is 250 without considering the
13609 transaction_length field. Using net_length_size(250) would return 1, but
13610 when adding the transaction_length field size to it (+1), the
13611 transaction_length becomes 251, and the field must be represented using two
13612 more bytes, so the correct transaction length must be in fact 253.
13613 */
13614 #ifndef NDEBUG
13615 2603399 ulonglong size_without_transaction_length = transaction_length;
13616 #endif
13617 // transaction_length will use at least TRANSACTION_LENGTH_MIN_LENGTH
13618 2603399 transaction_length += TRANSACTION_LENGTH_MIN_LENGTH;
13619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2603399 times.
2603399 assert(transaction_length - size_without_transaction_length == 1);
13620
2/2
✓ Branch 0 taken 2208327 times.
✓ Branch 1 taken 395072 times.
2603399 if (transaction_length >= 251ULL) {
13621 // transaction_length will use at least 3 bytes
13622 2208327 transaction_length += 2;
13623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2208327 times.
2208327 assert(transaction_length - size_without_transaction_length == 3);
13624
2/2
✓ Branch 0 taken 14836 times.
✓ Branch 1 taken 2193491 times.
2208327 if (transaction_length >= 65536ULL) {
13625 // transaction_length will use at least 4 bytes
13626 14836 transaction_length += 1;
13627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14836 times.
14836 assert(transaction_length - size_without_transaction_length == 4);
13628
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 14364 times.
14836 if (transaction_length >= 16777216ULL) {
13629 // transaction_length will use 9 bytes
13630 472 transaction_length += 5;
13631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 472 times.
472 assert(transaction_length - size_without_transaction_length == 9);
13632 }
13633 }
13634 }
13635 2603399 }
13636
13637 122974 rpl_sidno Gtid_log_event::get_sidno(bool need_lock) {
13638
2/2
✓ Branch 0 taken 64226 times.
✓ Branch 1 taken 58748 times.
122974 if (spec.gtid.sidno < 0) {
13639
2/2
✓ Branch 0 taken 63950 times.
✓ Branch 1 taken 276 times.
64226 if (need_lock)
13640 63950 global_sid_lock->rdlock();
13641 else
13642 276 global_sid_lock->assert_some_lock();
13643 64227 spec.gtid.sidno = global_sid_map->add_sid(sid);
13644
2/2
✓ Branch 0 taken 63950 times.
✓ Branch 1 taken 277 times.
64227 if (need_lock) global_sid_lock->unlock();
13645 }
13646 123090 return spec.gtid.sidno;
13647 }
13648
13649 120591 Previous_gtids_log_event::Previous_gtids_log_event(
13650 120591 const char *buf_arg, const Format_description_event *description_event)
13651 : binary_log::Previous_gtids_event(buf_arg, description_event),
13652
1/2
✓ Branch 0 taken 115659 times.
✗ Branch 1 not taken.
120591 Log_event(header(), footer()) {
13653
1/2
✓ Branch 0 taken 120591 times.
✗ Branch 1 not taken.
120591 DBUG_TRACE;
13654 120591 }
13655
13656 #ifdef MYSQL_SERVER
13657 78854 Previous_gtids_log_event::Previous_gtids_log_event(const Gtid_set *set)
13658 : binary_log::Previous_gtids_event(),
13659 Log_event(header(), footer(), Log_event::EVENT_NO_CACHE,
13660
1/2
✓ Branch 0 taken 78854 times.
✗ Branch 1 not taken.
78854 Log_event::EVENT_IMMEDIATE_LOGGING) {
13661
1/2
✓ Branch 0 taken 78854 times.
✗ Branch 1 not taken.
78854 DBUG_TRACE;
13662 78854 common_header->type_code = binary_log::PREVIOUS_GTIDS_LOG_EVENT;
13663 78854 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13664
1/2
✓ Branch 0 taken 78854 times.
✗ Branch 1 not taken.
78854 set->get_sid_map()->get_sid_lock()->assert_some_lock();
13665
1/2
✓ Branch 0 taken 78854 times.
✗ Branch 1 not taken.
78854 buf_size = set->get_encoded_length();
13666 uchar *buffer =
13667
1/2
✓ Branch 0 taken 78854 times.
✗ Branch 1 not taken.
78854 (uchar *)my_malloc(key_memory_log_event, buf_size, MYF(MY_WME));
13668
1/2
✓ Branch 0 taken 78854 times.
✗ Branch 1 not taken.
78854 if (buffer != nullptr) {
13669
1/2
✓ Branch 0 taken 78854 times.
✗ Branch 1 not taken.
78854 set->encode(buffer);
13670 78854 register_temp_buf((char *)buffer);
13671 }
13672 78854 buf = buffer;
13673 // if buf is empty, is_valid will be false
13674 78854 common_header->set_is_valid(buf != nullptr);
13675 78854 }
13676
13677 3879 int Previous_gtids_log_event::pack_info(Protocol *protocol) {
13678 3879 size_t length = 0;
13679
1/2
✓ Branch 0 taken 3879 times.
✗ Branch 1 not taken.
3879 char *str = get_str(&length, &Gtid_set::default_string_format);
13680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3879 times.
3879 if (str == nullptr) return 1;
13681
1/2
✓ Branch 0 taken 3879 times.
✗ Branch 1 not taken.
3879 protocol->store_string(str, length, &my_charset_bin);
13682
1/2
✓ Branch 0 taken 3879 times.
✗ Branch 1 not taken.
3879 my_free(str);
13683 3879 return 0;
13684 }
13685 #endif // MYSQL_SERVER
13686
13687 #ifndef MYSQL_SERVER
13688 1877 void Previous_gtids_log_event::print(FILE *,
13689 PRINT_EVENT_INFO *print_event_info) const {
13690 1877 IO_CACHE *const head = &print_event_info->head_cache;
13691 1877 char *str = get_str(nullptr, &Gtid_set::commented_string_format);
13692
1/2
✓ Branch 0 taken 1877 times.
✗ Branch 1 not taken.
1877 if (str != nullptr) {
13693
2/2
✓ Branch 0 taken 1713 times.
✓ Branch 1 taken 164 times.
1877 if (!print_event_info->short_form) {
13694 1713 print_header(head, print_event_info, false);
13695 1713 my_b_printf(head, "\tPrevious-GTIDs\n");
13696 }
13697 1877 my_b_printf(head, "%s\n", str);
13698 1877 my_free(str);
13699 }
13700 1877 }
13701 #endif
13702
13703 49441 int Previous_gtids_log_event::add_to_set(Gtid_set *target) const {
13704
1/2
✓ Branch 0 taken 49441 times.
✗ Branch 1 not taken.
49441 DBUG_TRACE;
13705 49441 size_t end_pos = 0;
13706
2/4
✓ Branch 0 taken 49441 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49441 times.
49441 size_t add_size = DBUG_EVALUATE_IF("gtid_has_extra_data", 10, 0);
13707 /* Silently ignore additional unknown data at the end of the encoding */
13708
2/6
✓ Branch 0 taken 49441 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49441 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
49441 PROPAGATE_REPORTED_ERROR_INT(
13709 target->add_gtid_encoding(buf, buf_size + add_size, &end_pos));
13710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49441 times.
49441 assert(end_pos <= buf_size);
13711 49441 return 0;
13712 49441 }
13713
13714 35982 char *Previous_gtids_log_event::get_str(
13715 size_t *length_p, const Gtid_set::String_format *string_format) const {
13716
1/2
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
35982 DBUG_TRACE;
13717
1/2
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
35982 Sid_map sid_map(nullptr);
13718
1/2
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
35982 Gtid_set set(&sid_map, nullptr);
13719
3/8
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35982 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 35982 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
35982 DBUG_PRINT("info", ("temp_buf=%p buf=%p", temp_buf, buf));
13720
2/4
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35982 times.
35982 if (set.add_gtid_encoding(buf, buf_size) != RETURN_STATUS_OK) return nullptr;
13721
1/2
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
35982 set.dbug_print("set");
13722
1/2
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
35982 size_t length = set.get_string_length(string_format);
13723
3/8
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 35982 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 35982 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
35982 DBUG_PRINT("info", ("string length= %lu", (ulong)length));
13724
1/2
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
35982 char *str = (char *)my_malloc(key_memory_log_event, length + 1, MYF(MY_WME));
13725
1/2
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
35982 if (str != nullptr) {
13726
1/2
✓ Branch 0 taken 35982 times.
✗ Branch 1 not taken.
35982 set.to_string(str, false /*need_lock*/, string_format);
13727
2/2
✓ Branch 0 taken 3879 times.
✓ Branch 1 taken 32103 times.
35982 if (length_p != nullptr) *length_p = length;
13728 }
13729 35982 return str;
13730 35982 }
13731
13732 #ifdef MYSQL_SERVER
13733 78824 bool Previous_gtids_log_event::write_data_body(Basic_ostream *ostream) {
13734
1/2
✓ Branch 0 taken 78824 times.
✗ Branch 1 not taken.
78824 DBUG_TRACE;
13735
3/8
✓ Branch 0 taken 78824 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 78824 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 78824 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
78824 DBUG_PRINT("info", ("size=%d", static_cast<int>(buf_size)));
13736
1/2
✓ Branch 0 taken 78824 times.
✗ Branch 1 not taken.
78824 bool ret = wrapper_my_b_safe_write(ostream, buf, buf_size);
13737 78824 return ret;
13738 78824 }
13739
13740 31143 int Previous_gtids_log_event::do_update_pos(Relay_log_info *rli) {
13741 31143 rli->inc_event_relay_log_pos();
13742 31143 return 0;
13743 }
13744
13745 /**************************************************************************
13746 Transaction_context_log_event methods
13747 **************************************************************************/
13748
13749 13259 Transaction_context_log_event::Transaction_context_log_event(
13750 const char *server_uuid_arg, bool using_trans, my_thread_id thread_id_arg,
13751 13259 bool is_gtid_specified_arg)
13752 : binary_log::Transaction_context_event(thread_id_arg,
13753 is_gtid_specified_arg),
13754 Log_event(header(), footer(),
13755 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
13756 : Log_event::EVENT_STMT_CACHE,
13757
3/4
✓ Branch 0 taken 13201 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 13259 times.
✗ Branch 3 not taken.
13259 Log_event::EVENT_NORMAL_LOGGING) {
13758
1/2
✓ Branch 0 taken 13259 times.
✗ Branch 1 not taken.
13259 DBUG_TRACE;
13759 13259 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13760 13259 server_uuid = nullptr;
13761
2/4
✓ Branch 0 taken 13259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13259 times.
✗ Branch 3 not taken.
13259 sid_map = new Sid_map(nullptr);
13762
2/4
✓ Branch 0 taken 13259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13259 times.
✗ Branch 3 not taken.
13259 snapshot_version = new Gtid_set(sid_map);
13763
13764 /*
13765 Copy global_sid_map to a local copy to avoid the acquisition
13766 of the global_sid_lock for operations on top of this snapshot
13767 version.
13768 The Sid_map and Gtid_executed must be read under the protection
13769 of MYSQL_BIN_LOG.LOCK_commit to avoid race conditions between
13770 ordered commits in the storage engine and gtid_state update.
13771 */
13772
2/4
✓ Branch 0 taken 13259 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13259 times.
13259 if (mysql_bin_log.get_gtid_executed(sid_map, snapshot_version)) goto err;
13773
13774
1/2
✓ Branch 0 taken 13259 times.
✗ Branch 1 not taken.
13259 server_uuid = my_strdup(key_memory_log_event, server_uuid_arg, MYF(MY_WME));
13775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13259 times.
13259 if (server_uuid == nullptr) goto err;
13776
13777 // These two fields are only populated on event decoding.
13778 // Encoding is done directly from snapshot_version field.
13779 13259 encoded_snapshot_version = nullptr;
13780 13259 encoded_snapshot_version_length = 0;
13781
13782 // Debug sync point for SQL threads.
13783
7/12
✓ Branch 0 taken 13259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13258 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
13259 DBUG_EXECUTE_IF(
13784 "debug.wait_after_set_snapshot_version_on_transaction_context_log_event",
13785 {
13786 const char act[] =
13787 "now wait_for "
13788 "signal.resume_after_set_snapshot_version_on_transaction_context_"
13789 "log_event";
13790 assert(opt_debug_sync_timeout > 0);
13791 assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
13792 };);
13793
13794 13259 common_header->set_is_valid(true);
13795 13259 return;
13796
13797 err:
13798 common_header->set_is_valid(false);
13799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13259 times.
13259 }
13800 #endif // MYSQL_SERVER
13801
13802 27971 Transaction_context_log_event::Transaction_context_log_event(
13803 27971 const char *buffer, const Format_description_event *descr_event)
13804 : binary_log::Transaction_context_event(buffer, descr_event),
13805 Log_event(header(), footer()),
13806 27971 sid_map(nullptr),
13807
1/2
✓ Branch 0 taken 27971 times.
✗ Branch 1 not taken.
27971 snapshot_version(nullptr) {
13808
1/2
✓ Branch 0 taken 27971 times.
✗ Branch 1 not taken.
27971 DBUG_TRACE;
13809
2/4
✓ Branch 0 taken 27971 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27971 times.
27971 if (!is_valid()) return;
13810
13811 27971 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13812
13813
2/4
✓ Branch 0 taken 27971 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27971 times.
✗ Branch 3 not taken.
27971 sid_map = new Sid_map(nullptr);
13814
2/4
✓ Branch 0 taken 27971 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27971 times.
✗ Branch 3 not taken.
27971 snapshot_version = new Gtid_set(sid_map);
13815
1/2
✓ Branch 0 taken 27971 times.
✗ Branch 1 not taken.
27971 }
13816
13817 164918 Transaction_context_log_event::~Transaction_context_log_event() {
13818 82458 DBUG_TRACE;
13819
1/2
✓ Branch 0 taken 41230 times.
✗ Branch 1 not taken.
82460 if (server_uuid) my_free(const_cast<char *>(server_uuid));
13820 82460 server_uuid = nullptr;
13821
2/2
✓ Branch 0 taken 27971 times.
✓ Branch 1 taken 13259 times.
82460 if (encoded_snapshot_version)
13822 55942 my_free(const_cast<uchar *>(encoded_snapshot_version));
13823 82460 encoded_snapshot_version = nullptr;
13824
1/2
✓ Branch 0 taken 41230 times.
✗ Branch 1 not taken.
82460 delete snapshot_version;
13825
1/2
✓ Branch 0 taken 41229 times.
✗ Branch 1 not taken.
82458 delete sid_map;
13826 164920 }
13827
13828 size_t Transaction_context_log_event::to_string(char *buf, ulong len) const {
13829 DBUG_TRACE;
13830 return snprintf(buf, len, "server_uuid=%s\tthread_id=%u", server_uuid,
13831 thread_id);
13832 }
13833
13834 #ifdef MYSQL_SERVER
13835 int Transaction_context_log_event::pack_info(Protocol *protocol) {
13836 DBUG_TRACE;
13837 char buf[256];
13838 size_t bytes = to_string(buf, 256);
13839 protocol->store_string(buf, bytes, &my_charset_bin);
13840 return 0;
13841 }
13842 #endif
13843
13844 #ifndef MYSQL_SERVER
13845 void Transaction_context_log_event::print(
13846 FILE *, PRINT_EVENT_INFO *print_event_info) const {
13847 DBUG_TRACE;
13848 char buf[256];
13849 IO_CACHE *const head = &print_event_info->head_cache;
13850
13851 if (!print_event_info->short_form) {
13852 to_string(buf, 256);
13853 print_header(head, print_event_info, false);
13854 my_b_printf(head, "Transaction_context: %s\n", buf);
13855 }
13856 }
13857 #endif
13858
13859 #if defined(MYSQL_SERVER)
13860 int Transaction_context_log_event::do_update_pos(Relay_log_info *rli) {
13861 DBUG_TRACE;
13862 rli->inc_event_relay_log_pos();
13863 return 0;
13864 }
13865 #endif
13866
13867 26510 size_t Transaction_context_log_event::get_data_size() {
13868
1/2
✓ Branch 0 taken 26510 times.
✗ Branch 1 not taken.
26510 DBUG_TRACE;
13869
13870 26510 size_t size = Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN;
13871 26510 size += strlen(server_uuid);
13872
1/2
✓ Branch 0 taken 26510 times.
✗ Branch 1 not taken.
26510 size += get_snapshot_version_size();
13873
1/2
✓ Branch 0 taken 26510 times.
✗ Branch 1 not taken.
26510 size += get_data_set_size(&write_set);
13874
1/2
✓ Branch 0 taken 26510 times.
✗ Branch 1 not taken.
26510 size += get_data_set_size(&read_set);
13875
13876 26510 return size;
13877 26510 }
13878
13879 13257 size_t Transaction_context_log_event::get_event_length() {
13880 13257 return LOG_EVENT_HEADER_LEN + get_data_size();
13881 }
13882
13883 #ifdef MYSQL_SERVER
13884 13253 bool Transaction_context_log_event::write_data_header(Basic_ostream *ostream) {
13885
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 DBUG_TRACE;
13886 char buf[Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN];
13887
13888 13253 buf[ENCODED_SERVER_UUID_LEN_OFFSET] = (char)strlen(server_uuid);
13889 13253 int4store(buf + ENCODED_THREAD_ID_OFFSET, thread_id);
13890 13253 buf[ENCODED_GTID_SPECIFIED_OFFSET] = gtid_specified;
13891 13253 int4store(buf + ENCODED_SNAPSHOT_VERSION_LEN_OFFSET,
13892
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 get_snapshot_version_size());
13893 13253 int4store(buf + ENCODED_WRITE_SET_ITEMS_OFFSET, write_set.size());
13894 13253 int4store(buf + ENCODED_READ_SET_ITEMS_OFFSET, read_set.size());
13895
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 return wrapper_my_b_safe_write(
13896 ostream, (const uchar *)buf,
13897 26506 Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN);
13898 13253 }
13899
13900 13253 bool Transaction_context_log_event::write_data_body(Basic_ostream *ostream) {
13901
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 DBUG_TRACE;
13902
13903
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 if (wrapper_my_b_safe_write(ostream, (const uchar *)server_uuid,
13904 13253 strlen(server_uuid)) ||
13905
6/12
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13253 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13253 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13253 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 13253 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 13253 times.
26506 write_snapshot_version(ostream) || write_data_set(ostream, &write_set) ||
13906
2/4
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13253 times.
13253 write_data_set(ostream, &read_set))
13907 return true;
13908
13909 13253 return false;
13910 13253 }
13911
13912 13253 bool Transaction_context_log_event::write_snapshot_version(
13913 Basic_ostream *ostream) {
13914
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 DBUG_TRACE;
13915 13253 bool result = false;
13916
13917
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 uint32 len = get_snapshot_version_size();
13918
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 uchar *buffer = (uchar *)my_malloc(key_memory_log_event, len, MYF(MY_WME));
13919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13253 times.
13253 if (buffer == nullptr) return true;
13920
13921
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 snapshot_version->encode(buffer);
13922
2/4
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13253 times.
13253 if (wrapper_my_b_safe_write(ostream, buffer, len)) result = true;
13923
13924
1/2
✓ Branch 0 taken 13253 times.
✗ Branch 1 not taken.
13253 my_free(buffer);
13925 13253 return result;
13926 13253 }
13927
13928 26506 bool Transaction_context_log_event::write_data_set(
13929 Basic_ostream *ostream, std::list<const char *> *set) {
13930
1/2
✓ Branch 0 taken 26506 times.
✗ Branch 1 not taken.
26506 DBUG_TRACE;
13931
2/2
✓ Branch 0 taken 230656 times.
✓ Branch 1 taken 26506 times.
257162 for (std::list<const char *>::iterator it = set->begin(); it != set->end();
13932 230656 ++it) {
13933 char buf[ENCODED_READ_WRITE_SET_ITEM_LEN];
13934 230656 const char *hash = *it;
13935 230656 uint16 len = strlen(hash);
13936
13937 230656 int2store(buf, len);
13938
1/2
✓ Branch 0 taken 230656 times.
✗ Branch 1 not taken.
230656 if (wrapper_my_b_safe_write(ostream, (const uchar *)buf,
13939
2/4
✓ Branch 0 taken 230656 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 230656 times.
461312 ENCODED_READ_WRITE_SET_ITEM_LEN) ||
13940
2/4
✓ Branch 0 taken 230656 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 230656 times.
230656 wrapper_my_b_safe_write(ostream, (const uchar *)hash, len))
13941 return true;
13942 }
13943
13944 26506 return false;
13945 26506 }
13946 #endif
13947
13948 27968 bool Transaction_context_log_event::read_snapshot_version() {
13949
1/2
✓ Branch 0 taken 27968 times.
✗ Branch 1 not taken.
27968 DBUG_TRACE;
13950
2/4
✓ Branch 0 taken 27968 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27968 times.
27968 assert(snapshot_version->is_empty());
13951
13952
1/2
✓ Branch 0 taken 27968 times.
✗ Branch 1 not taken.
27968 global_sid_lock->wrlock();
13953
1/2
✓ Branch 0 taken 27968 times.
✗ Branch 1 not taken.
27968 enum_return_status return_status = global_sid_map->copy(sid_map);
13954
1/2
✓ Branch 0 taken 27968 times.
✗ Branch 1 not taken.
27968 global_sid_lock->unlock();
13955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27968 times.
27968 if (return_status != RETURN_STATUS_OK) return true;
13956
13957 55936 return snapshot_version->add_gtid_encoding(encoded_snapshot_version,
13958
1/2
✓ Branch 0 taken 27968 times.
✗ Branch 1 not taken.
27968 encoded_snapshot_version_length) !=
13959 27968 RETURN_STATUS_OK;
13960 27968 }
13961
13962 53016 size_t Transaction_context_log_event::get_snapshot_version_size() {
13963
1/2
✓ Branch 0 taken 53016 times.
✗ Branch 1 not taken.
53016 DBUG_TRACE;
13964
1/2
✓ Branch 0 taken 53016 times.
✗ Branch 1 not taken.
53016 size_t result = snapshot_version->get_encoded_length();
13965 53016 return result;
13966 53016 }
13967
13968 53020 int Transaction_context_log_event::get_data_set_size(
13969 std::list<const char *> *set) {
13970
1/2
✓ Branch 0 taken 53020 times.
✗ Branch 1 not taken.
53020 DBUG_TRACE;
13971 53020 int size = 0;
13972
13973
2/2
✓ Branch 0 taken 461613 times.
✓ Branch 1 taken 53020 times.
514633 for (std::list<const char *>::iterator it = set->begin(); it != set->end();
13974 461613 ++it)
13975 461613 size += ENCODED_READ_WRITE_SET_ITEM_LEN + strlen(*it);
13976
13977 53020 return size;
13978 53020 }
13979
13980 230957 void Transaction_context_log_event::add_write_set(const char *hash) {
13981
1/2
✓ Branch 0 taken 230957 times.
✗ Branch 1 not taken.
230957 DBUG_TRACE;
13982
1/2
✓ Branch 0 taken 230957 times.
✗ Branch 1 not taken.
230957 write_set.push_back(hash);
13983 230957 }
13984
13985 void Transaction_context_log_event::add_read_set(const char *hash) {
13986 DBUG_TRACE;
13987 read_set.push_back(hash);
13988 }
13989
13990 /**************************************************************************
13991 View_change_log_event methods
13992 **************************************************************************/
13993
13994 #ifdef MYSQL_SERVER
13995 3845 View_change_log_event::View_change_log_event(const char *raw_view_id)
13996 : binary_log::View_change_event(raw_view_id),
13997 Log_event(header(), footer(), Log_event::EVENT_TRANSACTIONAL_CACHE,
13998
1/2
✓ Branch 0 taken 3845 times.
✗ Branch 1 not taken.
3845 Log_event::EVENT_NORMAL_LOGGING) {
13999
1/2
✓ Branch 0 taken 3845 times.
✗ Branch 1 not taken.
3845 DBUG_TRACE;
14000 3845 common_header->flags |= LOG_EVENT_IGNORABLE_F;
14001
14002 3845 common_header->set_is_valid(strlen(view_id) != 0);
14003 3845 }
14004 #endif
14005
14006 8769 View_change_log_event::View_change_log_event(
14007 8769 const char *buffer, const Format_description_event *descr_event)
14008 : binary_log::View_change_event(buffer, descr_event),
14009
1/2
✓ Branch 0 taken 8065 times.
✗ Branch 1 not taken.
8769 Log_event(header(), footer()) {
14010
1/2
✓ Branch 0 taken 8769 times.
✗ Branch 1 not taken.
8769 DBUG_TRACE;
14011
3/4
✓ Branch 0 taken 8065 times.
✓ Branch 1 taken 704 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8065 times.
8769 if (!is_valid()) return;
14012 8769 common_header->flags |= LOG_EVENT_IGNORABLE_F;
14013
14014 // Change the cache/logging types to allow writing to the binary log cache
14015 8769 event_cache_type = EVENT_TRANSACTIONAL_CACHE;
14016 8769 event_logging_type = EVENT_NORMAL_LOGGING;
14017
1/2
✓ Branch 0 taken 8769 times.
✗ Branch 1 not taken.
8769 }
14018
14019 50456 View_change_log_event::~View_change_log_event() {
14020 25228 DBUG_TRACE;
14021 25228 certification_info.clear();
14022 50456 }
14023
14024 9118 size_t View_change_log_event::get_data_size() {
14025
1/2
✓ Branch 0 taken 9118 times.
✗ Branch 1 not taken.
9118 DBUG_TRACE;
14026
14027 9118 size_t size = Binary_log_event::VIEW_CHANGE_HEADER_LEN;
14028
1/2
✓ Branch 0 taken 9118 times.
✗ Branch 1 not taken.
9118 size += get_size_data_map(&certification_info);
14029
14030 9118 return size;
14031 9118 }
14032
14033 9118 size_t View_change_log_event::get_size_data_map(
14034 std::map<std::string, std::string> *map) {
14035
1/2
✓ Branch 0 taken 9118 times.
✗ Branch 1 not taken.
9118 DBUG_TRACE;
14036 9118 size_t size = 0;
14037
14038 9118 std::map<std::string, std::string>::iterator iter;
14039 9118 size += (ENCODED_CERT_INFO_KEY_SIZE_LEN + ENCODED_CERT_INFO_VALUE_LEN) *
14040 9118 map->size();
14041
2/2
✓ Branch 0 taken 10286 times.
✓ Branch 1 taken 9118 times.
19404 for (iter = map->begin(); iter != map->end(); iter++)
14042 10286 size += iter->first.length() + iter->second.length();
14043
14044 9118 return size;
14045 9118 }
14046
14047 310 size_t View_change_log_event::to_string(char *buf, ulong len) const {
14048
1/2
✓ Branch 0 taken 310 times.
✗ Branch 1 not taken.
310 DBUG_TRACE;
14049 310 return snprintf(buf, len, "view_id=%s", view_id);
14050 310 }
14051
14052 #ifdef MYSQL_SERVER
14053 224 int View_change_log_event::pack_info(Protocol *protocol) {
14054
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 DBUG_TRACE;
14055 char buf[256];
14056
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 size_t bytes = to_string(buf, 256);
14057
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 protocol->store_string(buf, bytes, &my_charset_bin);
14058 224 return 0;
14059 224 }
14060 #endif
14061
14062 #ifndef MYSQL_SERVER
14063 86 void View_change_log_event::print(FILE *,
14064 PRINT_EVENT_INFO *print_event_info) const {
14065
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 DBUG_TRACE;
14066 char buf[256];
14067 86 IO_CACHE *const head = &print_event_info->head_cache;
14068
14069
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 if (!print_event_info->short_form) {
14070
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 to_string(buf, 256);
14071
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 print_header(head, print_event_info, false);
14072
1/2
✓ Branch 0 taken 86 times.
✗ Branch 1 not taken.
86 my_b_printf(head, "View_change_log_event: %s\n", buf);
14073 }
14074 86 }
14075 #endif
14076
14077 #if defined(MYSQL_SERVER)
14078
14079 6701 int View_change_log_event::do_apply_event(Relay_log_info const *rli) {
14080 6701 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
14081
2/2
✓ Branch 0 taken 1420 times.
✓ Branch 1 taken 5281 times.
6701 if (state == GTID_STATEMENT_SKIP) return 0;
14082
14083
3/6
✓ Branch 0 taken 5281 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5281 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5281 times.
10562 if (state == GTID_STATEMENT_CANCEL ||
14084 5281 (state == GTID_STATEMENT_EXECUTE &&
14085
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5281 times.
5281 gtid_pre_statement_post_implicit_commit_checks(thd))) {
14086 uint error = thd->get_stmt_da()->mysql_errno();
14087 assert(error != 0);
14088 rli->report(ERROR_LEVEL, error, "Error executing View Change event: '%s'",
14089 thd->get_stmt_da()->message_text());
14090 thd->is_slave_error = true;
14091 return -1;
14092 }
14093
14094
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5279 times.
5281 if (!opt_bin_log) {
14095 2 return 0;
14096 }
14097
14098 /*
14099 The view change is going to be written directly into the binary log and
14100 its "data_written" field may change depending on local binlog-checksum
14101 settings.
14102
14103 As MTS keep track of the size of the events on its queue relying on events
14104 header data_written field, we must ensure that it should not change on the
14105 event instance in memory (by backing it up before writing into binary log
14106 and restoring it after it was written).
14107 */
14108 5279 size_t original_ev_data_written = common_header->data_written;
14109 5279 int error = mysql_bin_log.write_event(this);
14110
1/2
✓ Branch 0 taken 5279 times.
✗ Branch 1 not taken.
5279 if (original_ev_data_written)
14111 5279 common_header->data_written = original_ev_data_written;
14112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5279 times.
5279 if (error)
14113 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
14114 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
14115 "Could not write the VIEW CHANGE event in the binary log.");
14116
14117 5279 return (error);
14118 }
14119
14120 int View_change_log_event::do_update_pos(Relay_log_info *rli) {
14121 DBUG_TRACE;
14122 rli->inc_event_relay_log_pos();
14123 return 0;
14124 }
14125
14126 9118 bool View_change_log_event::write_data_header(Basic_ostream *ostream) {
14127
1/2
✓ Branch 0 taken 9118 times.
✗ Branch 1 not taken.
9118 DBUG_TRACE;
14128 char buf[Binary_log_event::VIEW_CHANGE_HEADER_LEN];
14129
14130 9118 memcpy(buf, view_id, ENCODED_VIEW_ID_MAX_LEN);
14131 9118 int8store(buf + ENCODED_SEQ_NUMBER_OFFSET, seq_number);
14132 9118 int4store(buf + ENCODED_CERT_INFO_SIZE_OFFSET, certification_info.size());
14133
1/2
✓ Branch 0 taken 9118 times.
✗ Branch 1 not taken.
9118 return wrapper_my_b_safe_write(ostream, (const uchar *)buf,
14134 18236 Binary_log_event::VIEW_CHANGE_HEADER_LEN);
14135 9118 }
14136
14137 9118 bool View_change_log_event::write_data_body(Basic_ostream *ostream) {
14138
1/2
✓ Branch 0 taken 9118 times.
✗ Branch 1 not taken.
9118 DBUG_TRACE;
14139
14140
2/4
✓ Branch 0 taken 9118 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9118 times.
9118 if (write_data_map(ostream, &certification_info)) return true;
14141
14142 9118 return false;
14143 9118 }
14144
14145 9118 bool View_change_log_event::write_data_map(
14146 Basic_ostream *ostream, std::map<std::string, std::string> *map) {
14147
1/2
✓ Branch 0 taken 9118 times.
✗ Branch 1 not taken.
9118 DBUG_TRACE;
14148 9118 bool result = false;
14149
14150 9118 std::map<std::string, std::string>::iterator iter;
14151
2/2
✓ Branch 0 taken 10286 times.
✓ Branch 1 taken 9118 times.
19404 for (iter = map->begin(); iter != map->end(); iter++) {
14152 uchar buf_key_len[ENCODED_CERT_INFO_KEY_SIZE_LEN];
14153 10286 uint16 key_len = iter->first.length();
14154 10286 int2store(buf_key_len, key_len);
14155
14156 10286 const char *key = iter->first.c_str();
14157
14158 uchar buf_value_len[ENCODED_CERT_INFO_VALUE_LEN];
14159 10286 uint32 value_len = iter->second.length();
14160 10286 int4store(buf_value_len, value_len);
14161
14162 10286 const char *value = iter->second.c_str();
14163
14164
1/2
✓ Branch 0 taken 10286 times.
✗ Branch 1 not taken.
10286 if (wrapper_my_b_safe_write(ostream, buf_key_len,
14165 10286 ENCODED_CERT_INFO_KEY_SIZE_LEN) ||
14166
2/4
✓ Branch 0 taken 10286 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10286 times.
✗ Branch 3 not taken.
10286 wrapper_my_b_safe_write(ostream, (const uchar *)key, key_len) ||
14167
2/4
✓ Branch 0 taken 10286 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10286 times.
✗ Branch 3 not taken.
10286 wrapper_my_b_safe_write(ostream, buf_value_len,
14168
2/4
✓ Branch 0 taken 10286 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10286 times.
20572 ENCODED_CERT_INFO_VALUE_LEN) ||
14169
2/4
✓ Branch 0 taken 10286 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10286 times.
10286 wrapper_my_b_safe_write(ostream, (const uchar *)value, value_len))
14170 return result;
14171 }
14172
14173 9118 return false;
14174 9118 }
14175
14176 #endif // MYSQL_SERVER
14177
14178 /*
14179 Updates the certification info map.
14180 */
14181 3842 void View_change_log_event::set_certification_info(
14182 std::map<std::string, std::string> *info, size_t *event_size) {
14183
1/2
✓ Branch 0 taken 3842 times.
✗ Branch 1 not taken.
3842 DBUG_TRACE;
14184 3842 certification_info.clear();
14185
14186 3842 *event_size = Binary_log_event::VIEW_CHANGE_HEADER_LEN;
14187 3842 std::map<std::string, std::string>::iterator it;
14188
2/2
✓ Branch 0 taken 4397 times.
✓ Branch 1 taken 3842 times.
8239 for (it = info->begin(); it != info->end(); ++it) {
14189
1/2
✓ Branch 0 taken 4397 times.
✗ Branch 1 not taken.
4397 std::string key = it->first;
14190
1/2
✓ Branch 0 taken 4397 times.
✗ Branch 1 not taken.
4397 std::string value = it->second;
14191
2/4
✓ Branch 0 taken 4397 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4397 times.
✗ Branch 3 not taken.
4397 certification_info[key] = value;
14192 4397 *event_size += it->first.length() + it->second.length();
14193 4397 }
14194 3842 *event_size +=
14195 3842 (ENCODED_CERT_INFO_KEY_SIZE_LEN + ENCODED_CERT_INFO_VALUE_LEN) *
14196 3842 certification_info.size();
14197 3842 }
14198
14199 size_t Transaction_payload_log_event::get_data_size() {
14200 /* purecov: begin inspected */
14201 DBUG_TRACE;
14202 assert(false);
14203 return 0;
14204 /* purecov: end */
14205 }
14206
14207 #ifdef MYSQL_SERVER
14208 6 uint8 Transaction_payload_log_event::get_mts_dbs(Mts_db_names *arg,
14209 Rpl_filter *rpl_filter
14210 [[maybe_unused]]) {
14211 6 Mts_db_names &mts_dbs = m_applier_ctx.get_mts_db_names();
14212
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS) {
14213 4 arg->name[0] = nullptr;
14214 4 arg->num = OVER_MAX_DBS_IN_EVENT_MTS;
14215 } else {
14216
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (int i = 0; i < mts_dbs.num; i++) arg->name[i] = mts_dbs.name[i];
14217 2 arg->num = mts_dbs.num;
14218 }
14219
14220 6 return arg->num;
14221 }
14222
14223 6 void Transaction_payload_log_event::set_mts_dbs(Mts_db_names &arg) {
14224 6 m_applier_ctx.reset();
14225 6 Mts_db_names &mts_dbs = m_applier_ctx.get_mts_db_names();
14226 6 mts_dbs.num = arg.num;
14227
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (mts_dbs.num < MAX_DBS_IN_EVENT_MTS) {
14228
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (int i = 0; i < arg.num; i++)
14229 // strndup already adds the string terminator
14230 2 mts_dbs.name[i] = strndup(arg.name[i], NAME_LEN);
14231 }
14232 #ifndef NDEBUG
14233 else
14234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 assert(mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS);
14235 #endif
14236 6 }
14237
14238 6 uint8 Transaction_payload_log_event::mts_number_dbs() {
14239 6 return m_applier_ctx.get_mts_db_names().num;
14240 }
14241
14242 24 int Transaction_payload_log_event::do_apply_event(Relay_log_info const *rli) {
14243
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 DBUG_TRACE;
14244 24 int res = 0;
14245 24 PSI_stage_info old_stage;
14246
14247 /* apply events in the payload */
14248
14249 binary_log::transaction::compression::Iterable_buffer it(
14250
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 m_payload, m_payload_size, m_uncompressed_size, m_compression_type);
14251
14252
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 thd->enter_stage(&stage_binlog_transaction_decompress, &old_stage, __func__,
14253 __FILE__, __LINE__);
14254
8/14
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 144 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 168 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 168 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 150 times.
✓ Branch 13 taken 18 times.
168 for (auto ptr : it) {
14255
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 THD_STAGE_INFO(thd, old_stage);
14256
3/4
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 144 times.
150 if ((res = apply_payload_event(rli, (const uchar *)ptr))) break;
14257
1/2
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
144 thd->enter_stage(&stage_binlog_transaction_decompress, &old_stage, __func__,
14258 __FILE__, __LINE__);
14259 24 }
14260
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 THD_STAGE_INFO(thd, old_stage);
14261
14262 24 return res;
14263 24 }
14264
14265 300 static bool shall_delete_event_after_apply(Log_event *ev) {
14266 300 bool res = false;
14267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 if (ev == nullptr) return res;
14268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 switch (ev->get_type_code()) {
14269 case binary_log::FORMAT_DESCRIPTION_EVENT:
14270 /*
14271 Format_description_log_event should not be deleted because it will
14272 be used to read info about the relay log's format; it will be
14273 deleted when the SQL thread does not need it, i.e. when this
14274 thread terminates.
14275 */
14276
14277 [[fallthrough]];
14278 case binary_log::ROWS_QUERY_LOG_EVENT:
14279 /*
14280 ROWS_QUERY_LOG_EVENT is destroyed at the end of the current statement
14281 clean-up routine.
14282 */
14283 res = false;
14284 break;
14285 300 default:
14286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 DBUG_PRINT("info", ("Deleting the event after it has been executed"));
14287 300 res = true;
14288 300 break;
14289 }
14290
14291 300 return res;
14292 }
14293
14294 150 bool Transaction_payload_log_event::apply_payload_event(
14295 Relay_log_info const *rli, const uchar *event_buf) {
14296
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 DBUG_TRACE;
14297 150 bool res = false;
14298 150 const uchar *ptr = event_buf;
14299 150 Log_event *ev = nullptr;
14300 150 bool copied_buffer = false;
14301 150 uchar *copy_buffer = nullptr;
14302
14303 /*
14304 disable checksums - there are no checksums for events inside the tple
14305 otherwise, the last 4 bytes would be truncated.
14306
14307 We do this by copying the fdle from the rli. Then we disable the checksum
14308 in the copy. Then we use it to decode the events in the payload instead
14309 of the original fdle.
14310
14311 We allocate the fdle copy in the stack.
14312
14313 TODO: simplify this by breaking the binlog_event_deserialize API
14314 and make it take a single boolean instead that states whether the
14315 event has a checksum in it or not.
14316 */
14317 150 Format_description_event *fde = rli->get_rli_description_event();
14318
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 Format_description_log_event fdle(fde->reader().buffer(), fde);
14319 150 fdle.footer()->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_OFF;
14320 150 fdle.register_temp_buf(const_cast<char *>(fde->reader().buffer()), false);
14321 150 size_t event_len = uint4korr(ptr + EVENT_LEN_OFFSET);
14322
2/4
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 150 times.
150 if (binlog_event_deserialize(ptr, event_len, &fdle, true, &ev)) {
14323 res = true;
14324 goto end;
14325 }
14326
14327
2/4
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 150 times.
150 if (!shall_delete_event_after_apply(ev)) {
14328 copy_buffer =
14329 (uchar *)my_malloc(key_memory_log_event, event_len, MYF(MY_WME));
14330 memcpy(copy_buffer, ptr, event_len);
14331 copied_buffer = true;
14332 } else {
14333 150 copy_buffer = const_cast<uchar *>(ptr);
14334 150 copied_buffer = false;
14335 }
14336
14337 150 ev->register_temp_buf((char *)copy_buffer, copied_buffer);
14338 150 ev->common_header->log_pos = header()->log_pos;
14339
14340 150 thd->server_id = ev->server_id; // use the original server id for logging
14341 150 thd->unmasked_server_id = ev->common_header->unmasked_server_id;
14342
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 thd->set_time(); // time the query
14343
1/2
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
150 thd->lex->set_current_query_block(nullptr);
14344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
150 if (!ev->common_header->when.tv_sec)
14345 my_micro_time_to_timeval(my_micro_time(), &ev->common_header->when);
14346 150 ev->thd = thd; // because up to this point, ev->thd == 0
14347
14348 // TODO: HATE THIS
14349
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 24 times.
150 if (is_mts_worker(thd)) {
14350 126 auto worker =
14351 static_cast<Slave_worker *>(const_cast<Relay_log_info *>(rli));
14352 126 this->worker = worker;
14353
14354 // set in the event context
14355 126 ev->future_event_relay_log_pos = this->future_event_relay_log_pos;
14356 126 ev->mts_group_idx = mts_group_idx;
14357 126 ev->worker = worker;
14358
14359 // set in the worker context
14360 126 worker->set_future_event_relay_log_pos(ev->future_event_relay_log_pos);
14361 126 worker->set_master_log_pos(static_cast<ulong>(ev->common_header->log_pos));
14362 126 worker->set_gaq_index(ev->mts_group_idx);
14363
14364
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 104 times.
126 if (ev->get_type_code() == binary_log::QUERY_EVENT)
14365 static_cast<Query_log_event *>(ev)
14366 22 ->set_skip_temp_tables_handling_by_worker();
14367
1/2
✓ Branch 0 taken 126 times.
✗ Branch 1 not taken.
126 res = ev->do_apply_event_worker(worker);
14368 } else {
14369 24 auto coord = const_cast<Relay_log_info *>(rli);
14370 24 ev->future_event_relay_log_pos = coord->get_future_event_relay_log_pos();
14371
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 res = ev->apply_event(coord);
14372 }
14373
14374
3/6
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 150 times.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
150 if (shall_delete_event_after_apply(ev)) delete ev;
14375
14376 end:
14377 150 return res;
14378 150 }
14379
14380 21 Log_event::enum_skip_reason Transaction_payload_log_event::do_shall_skip(
14381 Relay_log_info *rli) {
14382 21 return Log_event::do_shall_skip(rli);
14383 }
14384
14385 60 bool Transaction_payload_log_event::write(Basic_ostream *ostream) {
14386
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 DBUG_TRACE;
14387
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 auto codec = binary_log::codecs::Factory::build_codec(header()->type_code);
14388 60 auto buffer_size = MAX_DATA_LENGTH + LOG_EVENT_HEADER_LEN;
14389 unsigned char buffer[MAX_DATA_LENGTH + LOG_EVENT_HEADER_LEN];
14390
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 auto result = codec->encode(*this, buffer, buffer_size);
14391 60 size_t data_size = result.first + m_payload_size;
14392
14393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (result.second == true) goto end;
14394
14395
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 return write_header(ostream, data_size) ||
14396
2/4
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
60 wrapper_my_b_safe_write(ostream, (uchar *)buffer, result.first) ||
14397
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 wrapper_my_b_safe_write(ostream,
14398
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 reinterpret_cast<const uchar *>(m_payload),
14399
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
120 m_payload_size) ||
14400
2/4
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
120 write_footer(ostream);
14401 end:
14402 return true;
14403 60 }
14404
14405 37 int Transaction_payload_log_event::pack_info(Protocol *protocol) {
14406
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 std::ostringstream oss;
14407
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 oss << "compression='";
14408
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
74 oss << binary_log::transaction::compression::type_to_string(
14409
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 m_compression_type);
14410
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 oss << "', decompressed_size=";
14411
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
37 oss << m_uncompressed_size << " bytes";
14412
2/4
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
37 protocol->store(oss.str().c_str(), &my_charset_bin);
14413 37 return 0;
14414 37 }
14415
14416 154 bool Transaction_payload_log_event::ends_group() const { return true; }
14417
14418 #endif
14419
14420 #ifndef MYSQL_SERVER
14421 /**
14422 The default values for these variables should be values that are
14423 *incorrect*, i.e., values that cannot occur in an event. This way,
14424 they will always be printed for the first event.
14425 */
14426 4909 PRINT_EVENT_INFO::PRINT_EVENT_INFO()
14427 4909 : flags2_inited(false),
14428 4909 sql_mode_inited(false),
14429 4909 sql_mode(0),
14430 4909 auto_increment_increment(0),
14431 4909 auto_increment_offset(0),
14432 4909 charset_inited(false),
14433 4909 lc_time_names_number(~0),
14434 4909 charset_database_number(ILLEGAL_CHARSET_INFO_NUMBER),
14435 4909 default_collation_for_utf8mb4_number(ILLEGAL_CHARSET_INFO_NUMBER),
14436 4909 sql_require_primary_key(0xff),
14437 4909 thread_id(0),
14438 4909 thread_id_printed(false),
14439 4909 default_table_encryption(0xff),
14440 4909 base64_output_mode(BASE64_OUTPUT_UNSPEC),
14441 4909 printed_fd_event(false),
14442 4909 have_unflushed_events(false),
14443 4909 skipped_event_in_transaction(false),
14444
1/2
✓ Branch 0 taken 4909 times.
✗ Branch 1 not taken.
4909 ddl_skip_rewrite(false) {
14445 /*
14446 Currently we only use static PRINT_EVENT_INFO objects, so zeroed at
14447 program's startup, but these explicit memset() is for the day someone
14448 creates dynamic instances.
14449 */
14450 4909 memset(db, 0, sizeof(db));
14451 4909 memset(charset, 0, sizeof(charset));
14452 4909 memset(time_zone_str, 0, sizeof(time_zone_str));
14453 4909 delimiter[0] = ';';
14454 4909 delimiter[1] = 0;
14455 4909 myf const flags = MYF(MY_WME | MY_NABP);
14456
1/2
✓ Branch 0 taken 4909 times.
✗ Branch 1 not taken.
4909 open_cached_file(&head_cache, nullptr, nullptr, 0, flags);
14457
1/2
✓ Branch 0 taken 4909 times.
✗ Branch 1 not taken.
4909 open_cached_file(&body_cache, nullptr, nullptr, 0, flags);
14458
1/2
✓ Branch 0 taken 4909 times.
✗ Branch 1 not taken.
4909 open_cached_file(&footer_cache, nullptr, nullptr, 0, flags);
14459 4909 }
14460 #endif
14461
14462 #if defined(MYSQL_SERVER)
14463 1 Heartbeat_log_event::Heartbeat_log_event(
14464 1 const char *buf, const Format_description_event *description_event)
14465 : binary_log::Heartbeat_event(buf, description_event),
14466
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 Log_event(header(), footer()) {
14467
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 DBUG_TRACE;
14468 1 }
14469
14470 2092 Heartbeat_log_event_v2::Heartbeat_log_event_v2(
14471 2092 const char *buf, const Format_description_event *description_event)
14472 : binary_log::Heartbeat_event_v2(buf, description_event),
14473
1/2
✓ Branch 0 taken 2092 times.
✗ Branch 1 not taken.
2092 Log_event(header(), footer()) {
14474
1/2
✓ Branch 0 taken 2092 times.
✗ Branch 1 not taken.
2092 DBUG_TRACE;
14475 2092 }
14476 #endif
14477
14478 #ifdef MYSQL_SERVER
14479 /*
14480 This is a utility function that adds a quoted identifier into the a buffer.
14481 This also escapes any existence of the quote string inside the identifier.
14482
14483 SYNOPSIS
14484 my_strmov_quoted_identifier
14485 thd thread handler
14486 buffer target buffer
14487 identifier the identifier to be quoted
14488 length length of the identifier
14489 */
14490 81 size_t my_strmov_quoted_identifier(THD *thd, char *buffer,
14491 const char *identifier, size_t length) {
14492
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 int q = thd ? get_quote_char_for_identifier(thd, identifier, length) : '`';
14493 81 return my_strmov_quoted_identifier_helper(q, buffer, identifier, length);
14494 }
14495 #else
14496 66549 size_t my_strmov_quoted_identifier(char *buffer, const char *identifier) {
14497 66549 int q = '`';
14498 66549 return my_strmov_quoted_identifier_helper(q, buffer, identifier, 0);
14499 }
14500
14501 #endif
14502
14503 66630 size_t my_strmov_quoted_identifier_helper(int q, char *buffer,
14504 const char *identifier,
14505 size_t length) {
14506 66630 size_t written = 0;
14507 char quote_char;
14508
2/2
✓ Branch 0 taken 66565 times.
✓ Branch 1 taken 65 times.
66630 size_t id_length = (length) ? length : strlen(identifier);
14509
14510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66630 times.
66630 if (q == EOF) {
14511 (void)strncpy(buffer, identifier, id_length);
14512 return id_length;
14513 }
14514 66630 quote_char = (char)q;
14515 66630 *buffer++ = quote_char;
14516 66630 written++;
14517
2/2
✓ Branch 0 taken 257942 times.
✓ Branch 1 taken 66630 times.
324572 while (id_length--) {
14518
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 257919 times.
257942 if (*identifier == quote_char) {
14519 23 *buffer++ = quote_char;
14520 23 written++;
14521 }
14522 257942 *buffer++ = *identifier++;
14523 257942 written++;
14524 }
14525 66630 *buffer++ = quote_char;
14526 66630 return ++written;
14527 }
14528
14529 308521 std::pair<bool, binary_log::Log_event_basic_info> extract_log_event_basic_info(
14530 Log_event *log_event) {
14531
1/2
✓ Branch 0 taken 308521 times.
✗ Branch 1 not taken.
308521 DBUG_TRACE;
14532
14533 308521 binary_log::Log_event_basic_info event_info;
14534 308521 event_info.query_length = 0;
14535 308521 event_info.event_type = log_event->get_type_code();
14536
14537
2/2
✓ Branch 0 taken 35988 times.
✓ Branch 1 taken 272533 times.
308521 if (binary_log::QUERY_EVENT == event_info.event_type) {
14538 35988 Query_log_event *qlog_event = static_cast<Query_log_event *>(log_event);
14539 35988 event_info.query = qlog_event->query;
14540
1/2
✓ Branch 0 taken 35988 times.
✗ Branch 1 not taken.
35988 if (event_info.query != nullptr)
14541 35988 event_info.query_length = strlen(event_info.query);
14542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35988 times.
35988 if (event_info.query_length == 0) {
14543 assert(event_info.query == nullptr); /* purecov: inspected */
14544 return std::make_pair(true, event_info); /* purecov: inspected */
14545 }
14546 }
14547 308521 event_info.ignorable_event = log_event->is_ignorable_event();
14548
1/2
✓ Branch 0 taken 308521 times.
✗ Branch 1 not taken.
308521 return std::make_pair(false, event_info);
14549 308521 }
14550
14551 1599772 std::pair<bool, binary_log::Log_event_basic_info> extract_log_event_basic_info(
14552 const char *buf, size_t length,
14553 const binary_log::Format_description_event *fd_event) {
14554
1/2
✓ Branch 0 taken 1599772 times.
✗ Branch 1 not taken.
1599772 DBUG_TRACE;
14555
14556 1599772 binary_log::Log_event_basic_info event_info;
14557 1599772 event_info.query_length = 0;
14558
14559 1599772 uint header_size = fd_event->common_header_len;
14560 1599772 const char *query = nullptr;
14561
14562 /* Error if the event content is smaller than header size for the format */
14563
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1599772 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1599772 if (length < header_size) return std::make_pair(true, event_info);
14564
14565 1599772 event_info.event_type = (Log_event_type)buf[EVENT_TYPE_OFFSET];
14566
14567
2/2
✓ Branch 0 taken 528930 times.
✓ Branch 1 taken 1070842 times.
1599772 if (binary_log::QUERY_EVENT == event_info.event_type) {
14568 528930 event_info.query_length =
14569
1/2
✓ Branch 0 taken 528919 times.
✗ Branch 1 not taken.
528930 Query_log_event::get_query(buf, length, fd_event, &query);
14570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 528930 times.
528930 if (event_info.query_length == 0) {
14571 assert(query == nullptr); /* purecov: inspected */
14572 return std::make_pair(true, event_info); /* purecov: inspected */
14573 }
14574 528930 event_info.query = query;
14575 }
14576 1599772 event_info.ignorable_event =
14577 1599772 uint2korr(buf + FLAGS_OFFSET) & LOG_EVENT_IGNORABLE_F;
14578
1/2
✓ Branch 0 taken 1599772 times.
✗ Branch 1 not taken.
1599772 return std::make_pair(false, event_info);
14579 1599772 }
14580